Related
For a library written in ES6/7, I want to compile (to ES5) the library to a dist/ folder. I also want to run the tests (written in ES6/7) for this lib.
My dev dependencies look like this (package.json):
"devDependencies": {
"#babel/cli": "^7.4.4",
"#babel/core": "^7.4.5",
"#babel/preset-env": "^7.4.5",
"#babel/register": "^7.4.4",
"chai": "^4.2.0",
"mocha": "^6.1.4",
"sinon": "^7.3.2"
},
My build and test scripts looks like this (package.json):
"scripts": {
"test": "mocha --require #babel/register",
"build": "babel src -d dist --presets=#babel/preset-env"
},
Running npm run build works well. The dist/ folder gets populated with transpiled files.
Running npm run test does not seem to work - this is my problem.
> mocha --require #babel/register
/Users/dro/Repos/lib/node_modules/yargs/yargs.js:1163
else throw err
^
ReferenceError: regeneratorRuntime is not defined
Initially I got an import error, which was resolved by adding .babelrc file.
Below is my .babelrc file content.
{
"presets": ["#babel/preset-env"]
}
I was reading about regeneratorRuntime and it got me to this link about babel-polyfill where they explain I shouldn't need that polyfill.
This will emulate a full ES2015+ environment (no < Stage 4 proposals) and is intended to be used in an application rather than a library/tool.
What is needed to set this up properly?
I am not using webpack.
Testing in ES6 with Mocha and Babel 7. Look here: https://dev.to/bnorbertjs/my-nodejs-setup-mocha--chai-babel7-es6-43ei or http://jamesknelson.com/testing-in-es6-with-mocha-and-babel-6/
npm install --save #babel/runtime
npm install --save-dev #babel/plugin-transform-runtime
And, in .babelrc, add:
{
"presets": ["#babel/preset-env"],
"plugins": [
["#babel/transform-runtime"]
]
}
Look at the project documentation:
npm install --save-dev babel-register
In your package.json file make the following changes:
{
"scripts": {
"test": "mocha --require babel-register"
}
}
Some features will require a polyfill:
npm install --save-dev babel-polyfill
{
"scripts": {
"test": "mocha --require babel-polyfill --require babel-register"
}
}
Below steps are for applying Babel transformations & core-js polyfills for your tests file:
ð¡ All transformations are only done per current environment, so only what is needed to be transpiled/polyfilled, will be. Target environments may be defined from a .browserslist file or as a property in package.json file. (read more here)
Step 1: Install packages:
#babel/core (read why)
#babel/preset-env (read why)
#babel/register (read why)
core-js (read why)
Note that #babel/polyfill exists and uses core-js under the hood. However, it was deprecated in favor of using core-js directly.
Step 2: Create a Babel configuration file babel.config.js
(used to be .babelrc.js or a .json file).
Create this file at the root-level of your code.
The most basic configuration (for just testing and not bundling) would look like this:
module.exports = {
presets: [
['#babel/preset-env', {
"corejs": "3.26",
"useBuiltIns": "usage"
}],
};
corejs - This is the polyfills library and should be specified with the minor version, otherwise x.0 will be used.
It is needed when testing code on rather "old" Node versions, which do not support all of the language methods. This ofc depends on your own usage of such javascript methods. (for example String.prototype.replaceAll).
useBuiltIns - must be set in order for the corejs polyfills to be applied. Read about it in the official docs.
By default, #babel/preset-env will compile your code for the current environment, but you can specify a different environment by setting the "targets" option in the configuration.
Ofc, you can add more presets like #babel/preset-react for example, if your code it written in React, or any other plugins which are specifically needed for your code.
Step 3: Connect mocha to the babel configuration:
In your package.json file
Under the scripts section, simply write something like this:
"test": "mocha \"src/**/*.test.js\""
Create a .mocharc.json file with this content:
{
"exit": true,
"color": true,
"require": ["#babel/register"],
"ignore": "node_modules"
}
This will apply Babel transformations to all of your test files.
If you need need to apply some special global javascript before/to all of your tests, you can add another file to the require setting, for example, fixtures.cjs:
"require": ["#babel/register", "fixtures.cjs"],
fixtures.cjs:
Below example applies a chai (popular alongside Mocha) plugin for testing DOM-related code:
var chai = require('chai'),
chaiDOM = require('chai-dom');
// https://stackoverflow.com/questions/62255953/chai-usechaihttp-once-or-in-every-test-file
// https://mochajs.org/#global-teardown-fixtures
exports.mochaGlobalSetup = function () {
chai.use(chaiDOM);
}
Interesting reads:
Babel vs babel-core vs babel-runtime
How does mocha / babel transpile my test code on the fly?
I have updated the SDK using this instruction. And I ran the app. The app shows this error in red screen:
babelHelpers.readOnlyError is not a function. (In
âbabelHelpers.readOnlyError(ânewSizeâ)â, âbabelHelpers.readOnlyErrorâ
is undefined )
How can I solve this error?
I tried clearing the yarn cache, installing yarn packages again but do not work.
I found this webpage solving my problem.
Add the following in package.json:
"devDependencies": {
"babel-plugin-transform-remove-console": "6.9.4",
"babel-preset-expo": "^5.0.0"
}
make the .babelrc:
{
"presets": ["babel-preset-expo"],
"env": {
"production": {
"plugins": [
"transform-remove-console"
]
}
}
}
Update .babelrc and package.json
Delete node_modules folder
Install babel-plugin-transform-remove-console, babel-preset-expo. Run yarn or npm.
Run expo clearing cache using expo start -c
I would like to use the grunt-contrib-jasmine NPM package. It has various dependencies. Part of the dependency graph looks like this:
â⬠grunt-contrib-jasmine#0.4.1
â ââ⬠grunt-lib-phantomjs#0.2.0
â â ââ⬠phantomjs#1.8.2-2
Unfortunately, there's a bug in this version phantomjs which prevents it from installing correctly on Mac OS X. This is fixed in the latest version.
How can I get grunt-lib-phantomjs to use a newer version of phantomjs?
Some additional context:
grunt-contrib-jasmine explicitly requires version "~0.2.0" of grunt-lib-phantomjs, which explicitly requires version "~1.8.1" of phantomjs.
Adding phantomjs to my package's dependencies first has no effect; both versions are installed and grunt-contrib-jasmine still uses the older versions (see: When installing a package with NPM, can you tell it to use a different version of one of its dependencies?).
You can use npm shrinkwrap functionality, in order to override any dependency or sub-dependency.
I've just done this in a grunt project of ours. We needed a newer version of connect, since 2.7.3. was causing trouble for us. So I created a file named npm-shrinkwrap.json:
{
"dependencies": {
"grunt-contrib-connect": {
"version": "0.3.0",
"from": "grunt-contrib-connect#0.3.0",
"dependencies": {
"connect": {
"version": "2.8.1",
"from": "connect#~2.7.3"
}
}
}
}
}
npm should automatically pick it up while doing the install for the project.
(See: https://nodejs.org/en/blog/npm/managing-node-js-dependencies-with-shrinkwrap/)
As of npm cli v8.3.0 (2021-12-09) this can be solved using the overrides field of package.json. As described in StriplingWarrior's answer
For example, the project has typescript version 4.6.2 as direct development dependency and awesome-typescript-loader that uses old version 2.7 of typescript. Here is how you can tell npm to use version 4.6.2 of typescript for awesome-typescript-loader:
{
"name": "myproject",
"version": "0.0.0",
"scripts": ...
"dependencies": ...
"devDependencies": {
"typescript": "~4.6.2",
"awesome-typescript-loader": "^5.2.1",
...
},
"overrides": {
"awesome-typescript-loader": {
"typescript": "$typescript"
}
}
}
If you don't use typescript as direct development dependency, then you have to write 4.6.2 instead of $typescript in overrides section:
{
"name": "myproject",
"version": "0.0.0",
"scripts": ...
"dependencies": ...
"devDependencies": {
"awesome-typescript-loader": "^5.2.1",
...
},
"overrides": {
"awesome-typescript-loader": {
"typescript": "~4.6.2"
}
}
}
For using the latest version of dependency:
{
"name": "myproject",
"version": "0.0.0",
"scripts": ...
"dependencies": ...
"devDependencies": {
"awesome-typescript-loader": "^5.2.1",
...
},
"overrides": {
"awesome-typescript-loader": {
"typescript": "latest"
}
}
}
Same overrides can be used for both dependencies and devDependencies.
If you're using npm version >5 but <8.3.0: edit your package-lock.json: remove the library from "requires" section and add it under "dependencies".
For example, you want deglob package to use glob package version 3.2.11 instead of its current one. You open package-lock.json and see:
"deglob": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.0.tgz",
"integrity": "sha1-TUSr4W7zLHebSXK9FBqAMlApoUo=",
"requires": {
"find-root": "1.1.0",
"glob": "7.1.2",
"ignore": "3.3.5",
"pkg-config": "1.1.1",
"run-parallel": "1.1.6",
"uniq": "1.0.1"
}
},
Remove "glob": "7.1.2", from "requires", add "dependencies" with proper version:
"deglob": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/deglob/-/deglob-2.1.0.tgz",
"integrity": "sha1-TUSr4W7zLHebSXK9FBqAMlApoUo=",
"requires": {
"find-root": "1.1.0",
"ignore": "3.3.5",
"pkg-config": "1.1.1",
"run-parallel": "1.1.6",
"uniq": "1.0.1"
},
"dependencies": {
"glob": {
"version": "3.2.11"
}
}
},
Now remove your node_modules folder, run npm ci (or npm install for old version of node/npm) and it will add missing parts to the "dependencies" section.
As of NPM v8.3, the correct way to deal with this is via the overrides section of your package.json file.
If you need to make specific changes to dependencies of your
dependencies, for example replacing the version of a dependency with a
known security issue, replacing an existing dependency with a fork, or
making sure that the same version of a package is used everywhere,
then you may add an override.
Overrides provide a way to replace a package in your dependency tree
with another version, or another package entirely. These changes can
be scoped as specific or as vague as desired.
To make sure the package foo is always installed as version 1.0.0 no
matter what version your dependencies rely on:
{
"overrides": {
"foo": "1.0.0"
}
}
There are a variety of other, more nuanced configurations allowing you to only override a package when it's a dependency of a particular package hierarchy. For more details, check out https://docs.npmjs.com/cli/v8/configuring-npm/package-json#overrides
The only solution that worked for me (node 12.x, npm 6.x) was using npm-force-resolutions developed by #Rogerio Chaves.
First, install it by:
npm install npm-force-resolutions --save-dev
You can add --ignore-scripts if some broken transitive dependency scripts are blocking you from installing anything.
Then in package.json define what dependency should be overridden (you must set exact version number):
"resolutions": {
"your-dependency-name": "1.23.4"
}
and in "scripts" section add new preinstall entry:
"preinstall": "npm-force-resolutions",
Now, npm install will apply changes and force your-dependency-name to be at version 1.23.4 for all dependencies.
For those using yarn.
I tried using npm shrinkwrap until I discovered the yarn cli ignored my npm-shrinkwrap.json file.
Yarn has https://yarnpkg.com/lang/en/docs/selective-version-resolutions/ for this. Neat.
Check out this answer too: https://stackoverflow.com/a/41082766/3051080
Nested replacement with an entirely different package
Most of the strategies outlined in the other answers here work well if you are just interested in overriding the package's version number, but in our case, we needed to find a way to override a nested npm sub-dependency with a different package altogether. For details on why you would ever want to do this, please refer to the following question:
How to override a nested npm sub-dependency with a different package altogether (not just different package version number)?
Specify the tarball directly
For nested replacement of a package with an entirely different package using the npm-force-resolutions strategy that others have mentioned, you just need to provide a link to the tarball where you would normally specify the overriding version number.
As an example, for the case of replacing the vulnerable package, ansi-html, with the fixed fork of this package, ansi-html-community, your resolutions section of package.json should look like this:
"resolutions": {
"ansi-html": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz"
}
To find the link to the tarball, use the following command, modifying your registry as necessary:
npm view ansi-html-community dist.tarball --registry=https://registry.npmjs.org/
Also, note that for npm-force-resolutions to work when you run npm install, you will need a preinstall entry under the scripts section of package.json:
"scripts": {
"preinstall": "npx npm-force-resolutions"
}
#user11153 's answer worked for me locally, but when trying to do a clean install (aka deleting node_modules), I would get:
npm-force-resolutions: command not found
I had to update the preinstall script to be:
"preinstall": "npm i npm-force-resolutions && npm-force-resolutions"
Which ensures that npm-force-resolutions package is installed before attempting to run it.
That being said, if you're able to use yarn instead, I would do that and then use #Gus 's answer.
I had an issue where one of the nested dependency had an npm audit vulnerability, but I still wanted to maintain the parent dependency version. the npm shrinkwrap solution didn't work for me, so what I did to override the nested dependency version:
Remove the nested dependency under the 'requires' section in package-lock.json
Add the updated dependency under DevDependencies in package.json, so that modules that require it will still be able to access it.
npm i
I was about to go down the npm-force-resolutions route but it seems that simply including the dependency in my own package.json fixed the problem for me.
I believe this worked in my case because the original dependency allows for patch versions of the dependency in question that I wanted to update. Thus by manually including a newer version it still fulfilled the dependency of the original dependency and will use the one I've manually added.
Example
Problem
I need to update plyr to version 3.6.9 from 3.6.8
Mine
package.json
{
"dependencies": {
"react-plyr": "^3.2.0"
}
}
React Plyr
package.json
{
"dependencies": {
"plyr": "^3.6.8"
}
}
Notice for the plyr dependency it starts with ^ this means it can accept any minor patches. You can learn more about that here:
https://docs.npmjs.com/about-semantic-versioning#using-semantic-versioning-to-specify-update-types-your-package-can-accept
Updating Mine
This updates the plyr dependency from my package.json.
package.json
{
"dependencies": {
"plyr": "^3.6.9",
"react-plyr": "^3.2.0"
}
}
Based on the rest of the answers, I provide the same solution, but I display the package.json, as I struggled a little bit on where to place the override and how.
{
"name": "my-app",
"version": "snapshot",
"scripts": {
"ng": "ng",
"build-dev": "ng build --configuration development",
},
"private": true,
"dependencies": {
"#angular/animations": "~14.2.9",
"#angular/common": "~14.2.9"
...
},
"devDependencies": {
"#angular-devkit/build-angular": "^14.2.8",
....
},
"overrides": {
"loader-utils#>2.0.0 <3": "2.0.4",
"loader-utils#>3.0.0 <4": "3.2.1"
}
}
For November 2022 "loader-utils" security vulnerability, it was requested to
use the version 2.0.4, if you are in the 2.X
use the version 3.2.1, if you are in the 3.X
And to verify
add the package.json the override tag
delete the package-lock.json
run "npm install"
run "npm audit"
Run this first
npm i -D #types/eslint#8.4.3
it will solve the issue
As shown in the screen shot below I am not able to run gulp to concat the JavaScript files. Its saying that gulp is not defined.
I have tried the following commands:
npm install -g gulp
npm install gulp
npm install gulp --save-dev
I have also set the environment variables as following:
C:\Users\<user>\AppData\Roaming\npm;C:\Python27;C:\Users\<user>\AppData\Roaming\npm\node_modules;C:\Users\<user>\AppData\Roaming\npm\node_modules\gulp;
var concat = require('gulp-concat');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');
//script paths
var jsFiles = 'scripts/*.js',
jsDest = 'dist/scripts';
gulp.task('scripts', function() {
return gulp.src(jsFiles)
.pipe(concat('scripts.js'))
.pipe(gulp.dest(jsDest));
});
you just need to install and require gulp locally, you probably only installed it globally
At the command line
cd <project-root> && npm install --save-dev gulp
In your gulpfile.js
var gulp = require('gulp');
this is a different dependency than the command line dependency (that you installed globally). More specifically, it is the same NPM package, but the command line program will execute code usually from a different entry point in the NPM package then what require('X') will return.
If we go to the package.json file in the Gulp project on Github, it will tell the whole story:
{
"name": "gulp",
"description": "The streaming build system",
"version": "3.9.1",
"homepage": "http://gulpjs.com",
"repository": "gulpjs/gulp",
"author": "Fractal <contact#wearefractal.com> (http://wearefractal.com/)",
"tags": [ ],
"files": [
// ...
],
"bin": {
"gulp": "./bin/gulp.js"
},
"man": "gulp.1",
"dependencies": {
// ...
},
"devDependencies": {
// ...
},
"scripts": {
"prepublish": "marked-man --name gulp docs/CLI.md > gulp.1",
"lint": "eslint . && jscs *.js bin/ lib/ test/",
"pretest": "npm run lint",
},
"engines": {
"node": ">= 0.9"
},
"license": "MIT"
}
so at the command line:
$ gulp default
will execute this:
"bin": {
"gulp": "./bin/gulp.js"
},
on the other hand, require('gulp') in your code will return the value of this:
https://github.com/gulpjs/gulp/blob/master/index.js
normally we see this in a package.json file as:
"main": "index.js"
but since this is the default, they just omitted it (which is dumb IMO, better to be explicit, but they aren't the first project I have seen take the lame shorthand route.).
Its occurs on Windows and usually one of the following fixes it:
If you didn't, run npm install gulp on the project folder, even if
you have gulp installed globally.
Normally, It isn't a problem on Windows, but it could be a issue with
the PATH. The package will try to get the PATH from the environment,
but you can override it by adding exec_args to your gulp settings.
For example, on Ubuntu:
"exec_args": {
"path": "/bin:/usr/bin:/usr/local/bin"
}
Hope It will be OK.
Source: https://github.com/NicoSantangelo/sublime-gulp/issues/12
When I change my files while webpack-dev-server is running, the bundle's files are not updated.
Here are my webpack.config.js and package.json files, as you can see from my npm script, I've solved running webpack watch and webpack-dev-server in the same command (npm run watch & webpack-dev-server --content-base ./ --port 9966):
webpack.config.js:
'use strict';
var ReactStylePlugin = require('react-style-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var webpack = require('webpack');
module.exports = {
devtool: 'sourcemap',
entry: ['./js/main.js'],
output: {
filename: 'bundle.js',
path: __dirname + '/assets',
publicPath: __dirname + '/'
},
module: {
loaders: [
{
test: /\.js$/,
loaders: [
ReactStylePlugin.loader(),
'jsx-loader?harmony'
]
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('css-loader')
}
]
},
plugins: [
new ReactStylePlugin('bundle.css'),
new webpack.DefinePlugin({
'process.env': {
// To enable production mode:
//NODE_ENV: JSON.stringify('production')
}
})
]
}
package.json:
{
"name": "reactTest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "webpack --watch",
"build": "webpack",
"web": "npm run watch & webpack-dev-server --content-base ./ --port 9966"
},
"author": "",
"license": "ISC",
"devDependencies": {
"css-loader": "^0.10.1",
"extract-text-webpack-plugin": "^0.3.8",
"jsx-loader": "^0.13.1",
"react-style-webpack-plugin": "^0.4.0",
"style-loader": "^0.10.2",
"url-loader": "^0.5.5",
"webpack": "^1.8.5",
"webpack-dev-server": "^1.8.0"
},
"dependencies": {
"react": "^0.13.1",
"react-style": "^0.5.3"
}
}
my directory structure is:
assets
bundle.css
bundle.css.map
bundle.js
bundle.js.map
js
AppActions.js
Profile.css.js
ProfileList.js
main.js
AppConstants.js
AppStore.js
Profile.js
ResultPage.js
package.json
index.html
node_modules
webpack.config.js
every file inside assets directory is generated by webpack
In order to get webpack to watch my file changes (Ubuntu 14.04), I had to increase the number of watchers (I had increased the number before, but it was still too low):
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
Source in the official docs: https://webpack.github.io/docs/troubleshooting.html#not-enough-watchers
I first suspected the cause to be fsevents which doesn't work on Ubuntu, but this apparently wasn't the case.
Furthermore, because now the watching and re-compiling worked, but the automatic browser refresh part didn't work, I added the --inline param to the answer of #deowk which enables the "inline mode":
webpack-dev-server --content-base ./ --port 9966 --hot --inline
Quote from the official docs: "The easiest way to use Hot Module Replacement with the webpack-dev-server is to use the inline mode."
Source: https://webpack.github.io/docs/webpack-dev-server.html#hot-module-replacement
you need to run webpack-dev-server with the --hot flag:
webpack-dev-server --content-base ./ --port 9966 --hot
Then you can access the hot-loading version localhost:9966/webpack-dev-server/
You don't need to run watch as well.
update:
This entry in your webpack config must change:
entry: ['./js/main.js'], --> entry: ['webpack/hot/dev-server' , './js/main.js']
Change your publicPath entry:
publicPath: '/assets/'
#funkybunky identified the right problem but (IMHO) fixed it the wrong way. At least in my case, webpack was trying to watch every file it used, including a deep chain of thousands of files of dependencies pulled from npm. I added this to my config, per the docs:
devServer: {
watchOptions: {
ignored: /node_modules/
}
}
Of course you legitimately could have thousands of files that might need to be watched, in which case go ahead and raise the limit, but you're probably better off ignoring vendor libraries that aren't likely to change.
I'll put this here just in case it helps anyone. My problem was the same, but caused by inconsistent capitalization of directory names and webpack alias declaration.
I had a WebGL directory which i referenced in my aliases as webgl, and unfortunately this worked for the build, but didn't work for code watching.
In my case, the error was caused by an empty space in the directory name, by changing "Repository Name" by "RepositoryName", everything worked fine !
Figured I'd post my solution as well. I had the same problem getting Flutter apps to run on OS X due to my hard drive setup.
The gist is if your project folder is in a symlinked folder, detecting the file changes may not work on OS X. Previously, we were on Webpack 3.X, I believe, and live reload/refresh worked fine in the original folder. However, after upgrading to the latest Webpack (^5.75.0) and Webpack Dev Server (^4.11.1), the hot-reloading no longer worked for me.
My original project folder was:
/Users/blakemiller/h/somefolder/v2/my-widget
The "/h" there is a symlink to: /System/Volumes/Data/projects/home/web/
I'm not sure what happened when I upgraded OS X at some point, but the upgrade changed the folders in a way that I don't really understand.
Putting the folder here instead, fixed the issue for me (no symlink):
/Users/blakemiller/my-widget
I doubt this will work for many people, as my setup is probably pretty specific, but maybe it will help someone else save 5 hours down the road...