JS: nvmrc vs package.json engines? - javascript

I am trying to lock node and npm version in my javascript project to ensure other developers have those specific versions when building bundles to commit. I just added this to my package.json:
"engineStrict" : true,
"engines": {
"node" : "10.10.0",
"npm" : "6.5.0"
},
Will this enforce those versions definitively? I am unfamiliar with locking down versions since I am used to be the sole developer on frontend projects or inheriting projects that have had this set up.
Alternatively, is there a benefit of also adding an .nvmrc file that specifies the same version or is that redundant if I'm using engines?

Enforcing Node.js version
engineStrict is deprecated since npm v3, but you can set engine-strict=true in your .npmrc file. If you have engines set in package.json, an error will be thrown when someone installs on an unsupported Node.js version.
.nvmrc for developer convenience
To make it easier for other developers to use a supported Node.js version, you can add a .nvmrc file. Now other developers can run nvm use to automatically use a supported version.

Related

Is there any way to convert a Node project to Deno?

I want to convert a Node.js project to Deno. Is there any guide available?
My current project has lots of NPM files and it's already in TypeScript.
Any tips?
Deno and Node.js APIs are not compatible, of course you will be able to reuse all javascript/typescript code but you'll need to refactor or add polyfills.
To ease migration Deno provides a Node Compatibility library, std/node, which still needs a lot of work.
Fortunately require is one of the already supported polyfills
import { createRequire } from "https://deno.land/std/node/module.ts";
const require = createRequire(import.meta.url);
// Loads native module polyfill.
const path = require("path");
// Visits node_modules.
const leftPad = require("left-pad");
console.log(leftPad('5', 5, '0'))
If you run that example:
npm i left-pad
deno run --allow-read node.js
// 00005
As you can see left-pad was loaded correctly from node_modules/. So for NPM packages that do not rely on Node.js API, you can easily require them using std/node.
Here's a list of all supported modules
Right now, for the packages that rely heavily on Node.js API, the best thing you can do is rewrite them using Deno API.
As the project matures there will be easier ways to convert a Node.js project to Deno.
IMO for big projects working perfectly on Node.js it's not worth it to migrate them. Deno & Node.js can live together it's not one or the other. Build new projects on Deno if you prefer instead of migrating old ones.
Check out Denoify, it's a build tool that does what you want. You don't have to write the port the tool do it for you, it is all detailed in the docs.
Disclosure: I am the author.
Starting from Deno v1.15 there is Node.js compatibility mode which is unstable and comes with some caveats. There is also an issue in the repo tracking the progress of the Node Compat mode.
Quoting from the docs
Node.js compability mode
Starting with v1.15 Deno provides Node compatiblity mode that makes it
possible to run a subset of programs authored for Node.js directly in
Deno. Compatiblity mode can be activated by passing --compat flag in
CLI.
⚠️ Using compatiblity mode currently requires the --unstable flag. If
you intend to use CJS modules, the --allow-read flag is needed as
well.
⚠️ Package management is currently out of scope for Node.js
compatiblity mode. For the time being we suggest to keep using your
current solution (npm, yarn, pnpm).
Please checkout the docs for
Example
How it works?
Module Resolution
Node.js built-in modules
Typescript support
denoify demo:
#! /bin/sh
cd $(mktemp -d)
npm init -y
sed -i 's|"main": "index.js"|"main": "src/index.ts"|' package.json
mkdir src
cat >src/index.ts <<'EOF'
import { writeSync } from 'fs'
writeSync(1, "hello world\n")
EOF
echo '{"compilerOptions": { "outDir": "out" }}' >tsconfig.json
npm install denoify
npx denoify
deno run --allow-env=NODE_DEBUG deno_out/index.ts
input: src/index.ts
import { writeSync } from 'fs'
writeSync(1, "hello world\n")
output: deno_out/index.ts
import { writeSync } from 'https://deno.land/std#0.159.0/node/fs.ts'
writeSync(1, "hello world\n")

How to control that all developers use the same library version?

We develop in Angular with Visual Studio Code using GitHub as a code repository. This works fine, but recently we had a problem due to one of the developers having a different version of a certain library. Since installing with npm doesn't require to specify the version (it installs the latest) he ended up with a version different from the other developers.
One way to solve the problem is to put all the libraries in GitHub, but that seems overwhelming. What are the best practices to have all developers use the same version of javascript libraries?
Make sure package.json specifies the version of dependencies and that you commit this file
{
"dependencies": {
"foo": "1.2.3" exact version
"bar": ">1.2.3" greater than 1.2.3
"baz": "^1.2.3" compatible with 1.2.3, ie from 1.2.3 until below 2.0.0
}
}
More details on semantic versionning
package.json defines which range of versions can be installed, but package-lock.json defines which exact versions of all packages (all = includes dependencies of dependencies) are installed. You have to commit this file.
Also, prefer npm clean-install rather than npm install because it throws an error if the installed packages in the node modules folder don't match the ones defined in the package lock.

Cannot transpile node.js app from es6 to es5

I am using node.js to develop a service, I have been using es6, I am not quite sure if there is a need to use babel in this case to transpile the javascript es6 to es5 since the code is never executed from the browser directly.
Also one thing that was wondering me is when should I use babel to transpile nodejs es6 to es5? I tried to instal babel to do the transpiling just out of curiosity and running: npm run build I get the following error:
Error: EPERM: operation not permitted, scandir 'C:\Documents and
Settings'
That error seems like a Windows problem, not JS problem.
Unless you want to support servers with Node below version, I think, 4.0, I see no point in transpiling.
Node supports ES6 syntax natively in version 6.4 and above. Generally stable LTS version (currently v10.15.3) will support most current ES version (refer to https://nodejs.org/).
For specific functionality you can refer to https://node.green/ to cross reference with your node version.
As for the error, it is an npm bug that was fixed in v5.6 (https://github.com/npm/npm/issues/17747).
You can update your npm using npm install npm#latest -g.

Side affects installing node modules and changing Node.js version?

Are there any issues or side affects to installing node modules under a particular Node.js version, changing the version of Node.js (eg. with NVM or a general node upgrade), and using the previously installed node modules?
Yes there are! If I install a module tested against a certain version of node and thereafter I update my node version, I can’t guarantee that the module will still work as expected.
There is an optional field engines that can be set in the package.json; from here, the module publisher can specify the version of node needed for his module to work, e.g.
{ "engines" : { "node" : ">=4 <6" } }
This will send a warning message during the package installation if your node version is not supported.

When using Meteor, should I prefix npm with meteor?

When working on Meteor 1.3 projects, should I always prefix npm with meteor? In the Meteor documentation and in code examples I see both.
I suspect that I always want to do this:
$ meteor npm install --save some-package
But is there ever a situation, in a Meteor project, where I want to just use the system npm?
$ npm install --save some-package
Are people just using shorthand when they omit the meteor prefix?
Well, to be exact, it depends on what you want to perform.
The easy rationale is based on what Tom did not explicitely say in his answer:
$ meteor npm install … will use the local npm shipped / bundled with Meteor Tools. It is the official supported version for Meteor.
$ npm install … will use your global npm, which version might differ from Meteor's one.
In the case of npm, the difference might be unnoticeable.
Unfortunately, the situation is different for Node: Meteor 1.3 still relies on Node 0.10.43! Simply give a try with commands $ meteor node --version and $ node --version.
Meteor 1.4 is supposed to upgrade to Node 4.
Knowing that, you can still use $ node (without meteor prefix), as long as your script does not need to be executed later on by Meteor itself (typically through a build process). Even if it does, you should not have troubles if your script does not use advanced Node features (i.e. introduced after version 0.10.43).
At least there is no difference in using a global npm or the meteor encapsulated. For me, I always use meteor npm or meteor node because I do not need and do not want to install global software.
Also to know, the bundled node is always the release with best tested compatibility and so I always use that. Also on production environment, we have installed meteor and use the bundled npm and node when running our apps. No issues by now.
I also like to have all project related stuff inside the project folder and not globally. That means, that we do not install anything npm related globally but always local to the node-modules folder.
This gives us the opportunity to move and run our software on different self hosting environments without headages or compatibility issues even between projects with different releases on same system.
Be aware that before release 1.3.4.3 the meteor tool does not respect always latest tools but this is solved by now.
Cheers
Tom

Categories

Resources