Is there a variable that refers to the package base directory? - node.js

Is there a variable (or how to make such a variable) that refers to the package base directory (where package.json is)?
The use case:
I am using Babel to compile code from ES6 to ES5. ./src/ to ./dist/. Then I refer to the ./dist/ code in the main property of the package.json
The problem happens when ./src/ code uses files that are not JS, e.g. ./src/schemas/*.json. These files do not exist in ./dist/ folder. Therefore, when referring to non-JavaScript files from ./src/ I need to use a path that keeps a reference to ./src/ file.
I can already do this using ./../src/schemas/foo.json when requesting a file. Though, thats a fragile approach.

I know I can simply copy all the non-JavaScript files to ./dist/, but
duplication of content does not seem like an appropriate solution.
This is the appropriate solution.
Why ?
Your src folder should hold the source code of your project (not including dependencies & build routines)
Your dist folder is supposed to hold a standalone version of your app or website that you'll be able to distribute "as is" (you should be able to upload the content of dist via ssh/ftp or whatever to your remote server and it should be working)
Note: This thread is more about code organization than code itself (so anybody can have his opinion), but this is the kind of workflow yeoman and lots of build systems use.

Related

Nestjs incorrent dist folder structure with monorepo mode

How come it generates dist/apps/twitter and puts everything into this folder must be put just into dist folder? What can lead to this?
Expected dist folder structure:
dist:
--apps:
----twitter/src
--libs
This isn't "incorrect" per se. When Nest is in monorepo mode, it by default will use webpack to bundle the application code together to a single file. This of course can be overridden and tsc can be used instead to output all of the compiled TS code if that is preferred. When tsc compiles code that contains sources outside of a single directory (e.g. apps/twitter/src is the base directory but libs/whatever is imported as well) then Typescript does its best to maintain the directory structure in the resulting dist so that import paths do not end up getting messed up.
The reason for having the apps/twitter twice is because Nest sets the output directory of the build to be dist/apps/<app-name>, similarly to how Nx does. This is done so that if you end up having multiple applications, say apps/google, you can havedist/apps/twitter and dist/apps/google and not have their dists interfere with each other

Make node script packaged with zeit-pkg aware of full filesystem

I have a node script which uses command line parameters using the module commander.
I want to pack it with pkg, but I am running into some trouble.
Normally I would execute my script with:
node index.js --file ./test.csv
but the file argument could point to any folder in the user's filesystem.
I have looked into configuring the assets and scripts attributes for pkg in package.json, but it looks like you need to specify a folder in there, such as:
"pkg": {
"scripts": "build/**/*.js",
"assets": "views/**/*"
}
How can I make a zeit-pkg packged node script aware of any possible location in the filesystem?
I am simply building with pkg package.json , since in package.json I have the entry:
"bin" : "index.js"
In your pkg-packed source, add this in the beginning:
console.log("process.cwd() = " + process.cwd());
When you run your packaged exe this will tell you what
your executable sees as its working directory. You can
then interpret any relative arg-paths of your application
(like "./index.csv") relative to that.
It seems based on my experiments that pkg-applications have
full access to the file-system as long as your program knows
the absolute paths of the files you want to read or write
or even "require".
The only tricky thing seems to be relative paths.
The reason is that pkg wants you to be able to package
resource/asset -files into the executable and then access them
like you would any file at runtime. That is actually a
great feature but often more than you need.
If you don't need to package any (extra) files into your
executable then file-system access should be simple and
work just normally with absolute paths. You just need to
know "where you are" if you want to use relative paths.
I'm not affiliated with the pkg project so my answer is
not authoritative in any way. I hope zeit would put more
documentation about the file-system access into their site,
especially cross-platform. After doing some experimentation
myself it just seems accessing files by their absolute paths
works, on Windows.

require.context for node modules does not work with linked package

I created kind of a plug-in web site. Each plug-in follows a certain name standard and a contract. Inside my main.js I load all packages "dynamically" following the name standard:
const context = require.context("../../node_modules", true, /plugin\-\w+\/dist\/(index\.js|styles\.css)$/)
This requires a context throughout node_modules folder and loads all modules named "plugin-X". From within those modules it looks for "dist/index.js" and "dist/styles.css". Those later get imported:
context.keys().forEach(path => {/* do stuff */ })
This works super nice as long as the packages are installed using npm install path/to/tgz. However this does not give a pleasant developing experience. So in my plugin-X folder I use "npm link" and in my web site I use "npm link plugin-X".
when I start webpack now the whole thing explodes after creating 15K file handles. If I remove the node_modules folder inside "plugin-X" it works. However I need node_modules for building with babel and other stuff to recognize changes in src folder to rebuild and put new scripts into dist folder.
Is there any way I could do this? Or maybe another option I missed during my research on how this could be done?
Regards

Difference between lib and dist folders when packaging library using webpack?

Ive just published my first package (a react component) to npm but im having some trouble understanding the difference between what the lib directory is compared to the dist.
Currently I generate both lib and dist however my package "main" points to the dist unminified js file which has been built using webpack and output as UMD. The lib folder is built using babel taking the src and outputting to lib.
The dist folder contains both [unminified/minified].js files as well as [unminified/minified].css files.
My main confusion is with the lib folder since imports from there currently wouldn't work seeing as I just transform src -> lib meaning the scss references are still there and the scss files aren't transformed either.
I use CSS Modules (css-loader, styles-loader, postcss-loader etc) to generate my CSS files and this is where the confusion is since, wouldn't I also need to use webpack to generate my lib folder seeing as the scss files/import references need to be transformed to css?
Are you meant to have both lib and dist or is the UMD build in dist fulling the same purpose as that of having a lib folder?
If you are supposed to have both how would I achieve this, since I couldnt find any info regarding generating the lib folder when using CSS modules within your js files and still maintaing the same folder structure of that of src (while still generating dist)?
Usually the dist folder is for shipping a UMD that a user can use if they aren't using package management. The lib folder is what package.json main points to, and users that install your package using npm will consume that directly. The only use of the lib as opposed to src is to transform your source using babel and webpack to be more generally compatible, since most build processes don't run babel transforms on packages in node_modules.
As far as handling the style imports, it's probably a good idea to not import scss or css files in your source js that you export. This is because node can't import styles like that by default. If you have an example that demos your component, it makes sense to import the styles there. The common pattern is to publish minified and unminified css in the dist folder, and in your documentation tell the consumer to explicitly import the css file using whatever technique they prefer. I took this approach with redux bug reporter if you need an example. Hope that helps!
In general lib refers to libraries that are included in a package, dist on the other hand are distribution files for your project. As an example you could write a bunch of javascript and include jquery (which is a lib) and then when they're all bundled up you have a single dist file.
Ok think I found out how to do this. There is a babel plugin that allows you to use webpack loaders when running babel (babel-plugin-webpack-loaders). Thus my CSS mapping is inlined within the js file and the mapping hashes used are also the same as that used when building dist. Yay!

Can I put the npm node_modules directory outside of my 'webroot'

I'm new to Node but am enjoying myself so far. I was trying to move my node_modules (libraries) directory outside of the public 'webroot' and need advice and guidance.
I've setup my simple expressJS based Node project as follows:
/my_project
/config
/public
/node_modules
server.js
I was wondering if there was any way I could have the /node_modules dir outside of my webroot and not break my application. I'm just so used to keeping the bare minimum in my publicly exposed webroot and don't feel right with the libs being in there. Call me old fashioned but that's how I'm used to doing stuff in the PHP and C# world.
If I setup the project as follows:
/my_project
/config
/node_modules
/public
server.js
then it all goes wobbly and Node's require() magic breaks.
I've tried the following:
var express=require('../express'); which doesn't work either giving me the 'Cannot Find module' type error.
Is what I'm asking even possible, if so then how?
Are there any major risks with me having my libs in a webroot or have I missed something fundamental here with the way Node works.
What do you guys do, what is best practice for production apps? May I have some examples of your production practices and why.
1. Is it possible to have modules in a folder outside of the project
Yes.
2. Are there any major risks with having modules in a webroot?
Assuming that you by "webroot" mean in the root of the server or any folder outside of your project: yes. It is possible to install modules globally with npm using the g-flag: npm install -g express. This generally considered bad practice as different projects may depend on different versions of the same module. Installing locally allows different projects to have different versions.
If you're using version control and don't want to check in the external modules, a common (and standard in npm) pattern is to ignore ./node_modules and specify dependencies in a package.json file.
3. "What is best practice for production apps?"
Not a good fit for SO, but since I'm at it I'll give it a shot anyway. If you use grunt (a very popular task automation tool) you'll usually end up with a structure like this:
/my_project
/node_modules
/lib
# actual project files
/public
# files that are meant to be sent to clients
/test
package.json # specifies dependencies, main script, version etc
README.md # optional
This structure has the advantages of clearly separating core files, dependencies and any tests while keeping it all in the same folder.

Resources