Creating a Node NPM module in 9.2.0 to support older versions of Node - node.js

Now that Node 9.2.0 has all the new features of the language, how do I go about creating a node module that is backwards compatible with older versions?
If I have a small module that Node 9 supports out of the box, like this.
const {map} = require('lodash')
async function test (...args) {
return map(args, (item) => {
return `${item} yeah`
})
}
module.exports = test
Are there any was to use babel to transpile this for the specific backward version that I would need to support using babel env? Is there any way I can conditionally load those babel development dependencies, say installing this via Node 4 using post-install scripts?

It seems like this is one solution one downside of which is it requires babel-runtime as a dep just in case, even if the current version of node doesn't need it. But in 9.2.0 the code above is the built code, it's simply moved by babel.
Here's an example package.json and on install it will build the src.
{
"name": "example",
"version": "1.0.0",
"main": "lib/index.js",
"scripts": {
"build": "babel src -d lib",
"postinstall": "npm run build"
},
"dependencies": {
"babel-runtime": "^6.26.0",
"lodash": "^4.17.4"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-env": "^1.6.1"
},
"babel": {
"plugins": [
"transform-runtime"
],
"presets": [
[
"env",
{
"targets": {
"node": "current"
}
}
]
]
}
}

Related

Bad autocomplete in eslint-config-react-app: 'react/cjs/react.development'

Background
For a very simple ReactJS project, I wanted to
add ESLint capabilities :
npm install --save-dev eslint-config-react-app eslint#^8.0.0
package.json after installing ESLint :
{
"name": "reactjs-app",
"scripts": {
"dev": "next dev"
},
"dependencies": {
"next": "^12.1.4",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"eslint": "^8.12.0",
"eslint-config-react-app": "7.0.0"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
}
}
In the above package.json, none of the three dependencies next,
react, react-dom, depends on any ESLint package – neither
directly nor indirectly.
So all installed ESLint packages are dependencies of
eslint-config-react-app.
All the files needed for the project are in a zip file
available for download.
To try it out, just download, unpack and run npm install.
1
index.js :
// index.js
import { useState } from 'react';
function HomePage() {
const [showParagraph, setShowParagraph] = useState(true);
const showParagraphHandler = useCallback(() => {
setShowParagraph((prevToggle) => !prevToggle);
}, []);
console.log('App RUNNING');
console.log(showParagraph);
return (
<div className='app'>
<h1>Hi there!</h1>
<button onClick={showParagraphHandler}>A button</button>
</div>
);
}
export default HomePage;
The question
An observant reader will notice that the import for useCallback is
missing.
But autocompletion (in VS Code Ctrl + space)
wrongly suggests to import from
react/cjs/react.development, or from
react/cjs/react.production.min,
instead of from react which would have been more correct.
Why does this happen? – Is there a bug fix?
^ click to enlarge
References
README for eslint-config-react-app
All the project files in a zip file
Suggested solutions for the bug in this question
1
For me, the npm install command took about 5 minutes to complete.
The npm install command downloads and installs all packages in
package.json – including indirect packages.
Running npm run dev from the command line should start the
application in your default web browser.
Why does this happen? – Is there a bug fix?
It seems the reason is that #types/react is a missing dependency in
eslint-config-react-app so the obvious bug fix is to add
#types/react manually to your project by running :
npm install #types/react --save-dev
VS Code's autocompletion through Ctrl + space
now correctly suggests react.
1
Installing #types/react adds "#types/react": "^18.0.0", in your
package.json under "dependencies" :
{
"name": "reactjs-app",
"scripts": {
"dev": "next dev"
},
"dependencies": {
"#types/react": "^18.0.0",
"next": "^12.1.4",
"react": "^18.0.0",
"react-dom": "^18.0.0"
},
"devDependencies": {
"eslint": "^8.12.0",
"eslint-config-react-app": "7.0.0"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
}
}
1
If it doesn't work, try restarting VS Code.

Using external babel configuration

I'm using #babel/node package in my project
and when I run my project as:
npm run dev
I'm getting this message in cmd window:
> Using external babel configuration
> Location: "...(project folder path)\.babelrc"
And when I build my project jsx files, I received errors .
How to solve it?
Dev dependencies:
"devDependencies": {
"#babel/node": "^7.7.4",
"#babel/preset-env": "^7.7.6",
"babel-preset-env": "^1.7.0",
"nodemon": "^1.19.4"
}
.babelrc file:
{
"presets": ["next/babel", "#babel/preset-env"]
}
Had the same issue, removed "#babel/preset-env" in .babelrc file. Deleting this part solves the issue (worked for me).
My babel.rc for developing js apps using nodejs is like this:
{
"presets": [
["#babel/preset-env"],
],
"plugins": [
["#babel/transform-runtime"]
],
"env": {
"development": {
"sourceMaps": true,
"retainLines": true
}
}
}
And my dev script is like this:
"dev": "./node_modules/.bin/cross-env NODE_ENV=development ./node_modules/.bin/nodemon --exec ./node_modules/.bin/babel-node src/index.js | pino-pretty",
I use cross-env and pino, you can remove it.
I hope helpful.

gulp-merge fails to output gulp-main-bower-files after .pipe

I have a css build task that merges resources from bower dependencies and my own css.
The build task is part of project that uses git source control. The project has been running correctly for well over a year.
Up until yesterday, everything was working correctly on my windows laptop, when I reinstalled my npm dependencies that run the build task.
Below is a simplified example
gulpfile.js
var gulp = require('gulp'),
$ = require('gulp-load-plugins')();
gulp.task('default', function () {
return $.merge (
gulp.src('./bower.json')
.pipe($.mainBowerFiles('**/*.css', {
includeDev: 'exclusive',
group: 'css'
})
),
gulp.src(['./source/css/styles.css'])
)
.pipe($.plumber())
.pipe($.concat('stylesheet.css'))
.pipe(gulp.dest('./build/css'))
});
package.json
{
"name": "merge",
"version": "1.0.0",
"description": "",
"main": "gulpfile.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"gulp": "^3.9.1",
"gulp-concat": "^2.6.1",
"gulp-load-plugins": "^1.5.0",
"gulp-main-bower-files": "^1.6.2",
"gulp-merge": "^0.1.1",
"gulp-plumber": "^1.1.0",
}
}
And bower.json
{
"name": "merge",
"description": "",
"main": "gulpfile.js",
"authors": [
""
],
"license": "ISC",
"homepage": "",
"private": true,
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"test",
"tests"
],
"devDependencies": {
"normalize-css": "^7.0.0",
"reset-css": "^2.2.1"
},
"group": {
"css": [
"reset-css",
"normalize-css"
]
}
}
Prior to yesterday the task would merge both sources declared in $.merge(...). Since yesterdays' npm install I am finding that the merge will only output the result for the first declared source.
After some testing I have found that if I reverse the order of the merge sources than both sources are merged to the set output destination.
var gulp = require('gulp'),
$ = require('gulp-load-plugins')();
// the order of the sources has been reversed
gulp.task('default', function () {
return $.merge (
gulp.src(['./source/css/styles.css']),
gulp.src('./bower.json')
.pipe($.mainBowerFiles('**/*.css', {
includeDev: 'exclusive',
group: 'css'
})
)
)
.pipe($.plumber())
.pipe($.concat('stylesheet.css'))
.pipe(gulp.dest('./build/css'))
});
The problem with this solution is that that output content reversed, which may cause issues with style inheritance etc. This change to a successful output makes me think there may be an issue with how and where .pipe($.mainBowerFiles(...) is declared.
I've also tried replacing installed modules for gulp-merge and gulp-main-bower-files respectively with merge2 and main-bower-files.
Using either one or both solved the problem, however this isn't an ideal workaround as it means an update to the gulp task and installed modules.
This sudden failure to output tasks merge css ( or js ) in my project has real issues for any historic commit or branch in the project.
Is there away I can diagnose the failure of the original $.merge(...), or a way that I can retroactively replace gulp-merge with merge2 across all commits my git project and any branches?

unexpected token import in ES2017 with babel and Jest

I try to use Jest with bablejs and ES2017 in my project, according to the Jest Getting Started page and also Bablejs config for ES2017 this is my .babelrc file :
{
"presets": ["es2017"],
"env": {
"test": {
"presets": ["es2017"]
}
}
}
And my package.json is:
{
"name": "",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "jest"
},
"repository": {
"type": "git",
"url": ""
},
"author": "",
"license": "ISC",
"bugs": {
"url": ""
},
"homepage": "",
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-jest": "^21.2.0",
"babel-polyfill": "^6.26.0",
"babel-preset-es2017": "^6.24.1",
"jest": "^21.2.1"
}
}
When I type npm test to run all my test with jest i get these error :
){import StateList from './StateList';
^^^^^^
SyntaxError: Unexpected token import
It means it doesn't know import.
babel-preset-es2017 does not transform import statements, because it only includes the plugins: syntax-trailing-function-commas and
transform-async-to-generator.
When installing babel-preset-es2017 you also get a warning that it has been deprecated in favour of babel-preset-env, which contains everything that the es201x presets contained and more.
warning babel-preset-es2017#6.24.1: 🙌 Thanks for using Babel: we recommend using babel-preset-env now: please read babeljs.io/env to update!
As shown in the Migration guide from es2015 to env, it is a drop-in replacement.
npm install --save-dev babel-preset-env
And change your .babelrc to:
{
"presets": ["env"]
}
Do not confuse babel-preset-env with Babel's env option, which I have removed from your current config, since you are using the exact same presets for the test environment as for any other, so it doesn't have any effect.
You can configure babel-preset-env to only transform features that are not supported by the platform you target, for example { "targets": { "node": "current" } } will only transform features that aren't supported by the Node version you are running. If no targets are specified, it will transform everything. For details see the Env preset documentation.
Note: With the upcoming version 7 of Babel, the official packages will be published under the namespace #babel, which means that babel-preset-env will be #babel/preset-env.

Force Browserify to transform dependencies?

I'm working on two Node packages at once, let's call them Library and Consumer. Library is responsible for rendering a bunch of stuff in the browser. All Consumer does is import Library from 'library' and call Library(someConfigHere) -- it's basically just a test to make sure Library is doing what I expect in the browser.
I've npm linked Library into Consumer and am trying to run Browserify on Consumer, but I get this error: ParseError: 'import' and 'export' may appear only with 'sourceType: module'. Library does indeed contain an ES6 export statement, so I'm guessing that Browserify is only running against Consumer and not Library.
So my question is: is there any way to force Browserify to transform dependencies as well?
This is my package.json:
{
"name": "consumer",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "budo index.js --port $PORT",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"babel-preset-es2015": "^6.13.2",
"babel-preset-react": "^6.11.1",
"babelify": "^7.3.0",
"browserify-shim": "^3.8.12"
},
"browserify": {
"transform": [
"babelify"
]
},
"babel": {
"presets": [
"es2015",
"react"
]
}
}
This is Consumer's index.js:
import Library from 'library' // <= this is what isn't getting babelified
console.log(Library);
This is Library's index.js:
export default (config) => {
console.log('Testing testing')
}
Browserify transforms can be configured to be global, which means they will be applied to files within node_modules, too.
The configuration is per-transform. With babelify, you'd configure it like this:
browserify().transform("babelify", {
global: true
})
Or, if you are using the command line, like this:
browserify ... -t [ babelify --global ] ...
Or, to configure it in the package.json, it should be something like this (note the added square brackets):
"browserify": {
"transform": [
["babelify", { "global": true }]
]
}
Babelify also implements an ignore option, so it would be possible to configure it to transform only the files within node_modules that you want it to. There is more information here.
Another solution would be to include a similar browserify/babelify configuration in your library module's package.json. When processing dependencies, Browserify will check said dependency's pacakge.json files for transforms and will apply any that are configured.

Resources