Dirname in Nuxt - node.js

I am trying to read files in a directory but cannot because __dirname is undefined
nuxt.config.js
export default {
router: {
middleware: ['database']
},
build: {
extend: function (config, __ctx) {
config.node = {
fs: "empty",
module: "empty",
net: "empty",
};
},
},
}
What can be done to determine __dirname?

As far as I figured it out, Webpack always sets the __dirname to '/'. But probably not on server side.
Maybe this reference will help you resolve your issue: https://codeburst.io/use-webpack-with-dirname-correctly-4cad3b265a92
You didn't say much what you are trying to accomplish, but I will wrote down a solution for one of the most common issues which usually result in people trying to use __dirname constant. Maybe it will also help you ;)
Whenever I tried to use __dirname in Nuxt, it was because I had to make a workaround for the missing require.context functionality in server side process (SSR).
Doing some workarounds with require and __dirname usually caused even more issues.
The best solution if you are struggling with missing require.context in Nuxt server side process is to use Plugins. They can use require.context function and are available both on server side and on client side.
Overall, I think that you should try and find your files with webpack's context functionality and avoid using __dirname.
const files = require.context('~/', true, /\/your-file-name\/.*\.ts$/)
files.keys().map(key => {
// This is an example how to access your file's default export.
// You will probably have to amend it to make any use of it ;)
const file = files(key).default
})

Related

How can I use .vue files in Node.js *without* a bundler like webpack?

I'm trying to find a simple server-side rendering solution for Vue.js, but every example or tutorial I've found has dependencies I don't want to include that overcomplicate things: usually webpack, Vue Router, and Vuex.
I'm looking for a solution that runs in Node.js and can render a .vue file to a string, including any other .vue files it may reference.
const sfcContent = fs.readFileSync("./app.vue", "utf-8");
const props = {
foo: "bar",
};
const htmlString = await render(sfcContent, props);
console.log(htmlString);
async function render(sfcContent, props) {
// this is the function I'm looking for
}
http-vue-loader looks promising, as it does roughly what I'm looking for except in the browser instead of Node.js.
Any ideas what I should try?
You could look into the compiler-utils package https://github.com/vuejs/component-compiler-utils
Although, this will still require some tinkering on your end so I'm not sure if it'll be the way to go if you don't want to overcomplicate things.

How to make node cms modular

I want to make my node cms (at this moment only login,reg, articles) modular. Like you can add or remove any module just be deleting or adding folder. But i cant find any correct or smart or any way to do it. Have you any experience, guides or examples that can help?
I am relatively new in node.
At this moment it looks like this.
This question is a bit too broad in the context of creating a modular cms, however when talking about node modules, even if you just add or delete a folder you still have to require them in your code.
I would say that there are 2 types of plugins that you can have:
Supported plugins - plugins that you create and give the users the option to include them or not
Anonymous plugins - plugins that everyone can create, and need to be included in your application via some kind of interface.
The second type of plugins are more complicated, so I will refer only to the first type. An easy way to include them in your code is to have a JSON where you list the properties of each plugin, and then require each plugin in your code. Using try/catch will prevent your application from crashing if the plugin does not exist:
var allowedPlugins = [
{name: "login", path: "login/index.js", loaded: false, module: null},
{name: "reg", path: "reg/reg.js", loaded: false, module: null},
{name: "articles", path: "articles/all.js", loaded: false, module: null}
];
allowedPlugins.forEach((plug) => {
try {
var module = require(plug.path);
plug.loaded = true;
plug.module = module;
} catch(err) {}
});
Later in your code you can do:
if (allowedPlugins.login.loaded) {
var login = allowedPlugins.login.module;
login.doLogic(...)
}

How to compile ReactJS for use on server with command line arguments?

I've decided to try out ReactJS. Along with that, I've decided to use Gulp for compiling .jsx to .js, also for the first time.
I can compile it no problem for the client use with browserify. Here's my gulp task:
browserify("./scripts/main.jsx")
.transform(
babelify.configure({
presets: ["react"]
}))
.bundle()
.pipe(source('bundle.js'))
.pipe(gulp.dest('./scripts/'));
But since I use PHP to generate data, I need to get those data to node. If I use browserify, it will prevent me from using process.argv in node. I can save data to file and read that file in node, so I wouldn't need to pass the whole state to node, but I still need to pass the identifying arguments, so the node knows which file to load.
What should I use instead of browserify?
If you need to compile a React module to es5 for use on the server, use Babel itself.
A module that may help with reading and writing files is this one: https://nodejs.org/api/fs.html
Have you considered posting and getting from a database?
Here's how I solved it:
I have learnt that you can create standalone bundles with browserify, so I've compiled all the server code I need (components + rendering) as a standalone bundle. Then I have created small node script which is responsible only for reading arguments, loading data and sending it to the rendering code.
I'm not sure if this is a proper way how it should be done but it works.
Here's code for the "setup" script:
var fs = require('fs');
var Server = require('./server.js');
if (process.argv[2]) {
region = process.argv[2].toLowerCase().replace(/[^a-z0-9]/, '');
if (region != '') {
var data = JSON.parse(fs.readFileSync(__dirname + '/../tmp/' + region + '.json', 'utf8'));
console.log(Server.render(data.deal, data.region));
}
}
This way I only need to deploy two files and I still can easily compile jsx to js.

Webpack Aliases in Node JS Server code

I'm building an isomorphic React/React-Router/Redux/Webpack application and I'm attempting to implement server side rendering.
My directory looks like:
/client
/actions
/components
/containers
/server
/server.js
In my webpack config, I have aliases set up for all the folders inside client:
var path_base = path.resolve(__dirname, '..');
const resolve = path.resolve;
const base = function() {
var args = [path_base];
args.push.apply(args, arguments);
return resolve.apply(resolve,args);
};
const resolve_alias = base.bind(null, 'src/client');
const aliases = [
'actions',
'components',
'constants',
'containers',
'middleware',
'reducers',
'routes',
'store',
'styles',
'utils',
'validation'
];
so that inside the code that gets bundled by webpack, I can do:
import { Widget } from 'components';
and that import gets resolved by webpack.
Now in my server code, in order to do the rendering, I have to import some of my client files, like routes/index.js. The problem I'm running into when I import my routes file, it's using a webpack alias to another file, say components or containers so naturally, the node js require system can't resolve it.
How do I fix something like that? I looked at this question and it talks about essentially setting up the same aliases that exist in webpack with mock-require. But then the issue becomes that my routes file imports all my components which then all import things like stylesheets, images, etc. Should I then be using something like webpack-isomorphic-tools?
The guides I've been looking at (this for example) are all great at showing how server side rendering is accomplished but none of them really talk about how to resolve all the requires and whatnot.
After battling with this issue for 2 days I settled on babel-plugin-webpack-alias.
What you need to do to resolve paths with that is:
$ npm install --save-dev babel-plugin-webpack-alias
Add the plugin to your .babelrc
Add the aliases to your webpack.config (make sure you use path.join())
Refer to this post if you have problems loading styles
The other option I tried was universal-webpack but I found it to be a bit verbose. If you want to see roughly how the whole server-side loading works, you can check out this video.
If you really want them, run your server side code through babel and use this plugin: https://www.npmjs.com/package/babel-plugin-module-alias which will let you do the same thing as webpack.
Edit: This one works a lot better: https://github.com/jagrem/babel-resolve-relative-module it allows multiple paths
Try to use NODE_PATH. Node will always look for a module in this path during require calls. It allows to short cut your relative paths as you want.
// turn this
import {Widget} from '../../components';
// into this
import {Widget} from 'components';
See Node.js docs for more information.
P.S. this thing is very sensitive, so use it carefully. Now your code tightly depends from the environment and may break somewhere.
If you use webpack-isomorphic-tools then it'll take your webpack config into account for your server side which will make all your aliases work.
https://www.npmjs.com/package/webpack-isomorphic-tools

NodeJs - How to avoid relative paths with import keyword

Per several github docs, I have tried this, although it is really for the require keyword, as the very first line in the first server file fired [index.js]:
process.env.NODE_PATH = 'app';
require('module').Module._initPaths();
It didn't work. Then I read up in webpack to do this, but still it does not work:
resolve: {
root: path.resolve(path.join(__dirname + '/app')),
alias: {
app: 'app',
component: 'app/components',
utility: 'app/utils'
},
extensions: ['', '.js', '.jsx']
},
How do I avoid the endless '../../../../' as my project goes deeper as I do not want to keep doing this:
Import MyComponent from '../../../../../Whatever' ?
Thanks
Currently I am using quite the same solution, no 6 in this list.
process.env.NODE_PATH = __dirname;
require('module').Module._initPaths();
Which enables me to call all my js files by folder/filename wherever I am in my code base, e.g.
require('services/userService');
This is a quite ugly solution since it relies on a private Node.js core method, this is also a hack that might stop working on the previous or next version of node.
I also asked the same question on Quora with some answers.

Resources