Webpack always resolves packages from the root of node_modules #1037
Description
Environment
Provide version numbers for the following components (information can be retrieved by running tns info
in your project folder or by inspecting the package.json
of the project):
-
CLI: 6.1.0
-
Cross-platform modules: 6.1.0
-
Android Runtime: 6.1.0
-
iOS Runtime: 6.1.0
-
Plugin(s): "tslib": "1.8.0"
-
Node.js: 10.15.1
-
Please, attach your package.json and webpack.config.js as these configurations are usually critical for investigating issues with webpack
{
"nativescript": {
"id": "org.nativescript.myApp",
"tns-android": {
"version": "6.1.0"
},
"tns-ios": {
"version": "6.1.0"
}
},
"description": "NativeScript Application",
"license": "SEE LICENSE IN <your-license-filename>",
"repository": "<fill-your-repository-here>",
"dependencies": {
"nativescript-theme-core": "~1.0.6",
"tns-core-modules": "~6.1.0",
"tslib": "1.8.0"
},
"devDependencies": {
"nativescript-dev-webpack": "~1.2.0"
},
"gitHead": "9475c272a4c74ea6baf24d578bdf46c23a400fea",
"readme": "NativeScript Application"
}
Describe the bug
During module resolution webpack always uses the packages at the root of project's node_modules. This is a problem when multiple versions of the same package are required and installed. For example, tns-core-modules
depend on tslib
with version ^1.9.3
. In case you have tslib
1.8.0 installed in your project, npm
will install it at the root of node_modules
and in node_modules/tns-core-modules/node_modules
another version of tslib
will be installed.
During webpack build, the packages are searched for in the order defined here.
According to webpack's documentation:
Absolute and relative paths can both be used, but be aware that
they will behave a bit differently.
A relative path will be scanned similarly to how Node scans for node_modules,
by looking through the current directory as well as its ancestors
(i.e. ./node_modules, ../node_modules, and on).
With an absolute path, it will only search in the given directory.
So, what happens on our side - when webpack resolves the modules, it sees tns-core-modules
import(require) something from tslib
and starts resolving tslib
. It checks the resolve.modules
array and searches for tslib
in the order described in the webpack.config.js, i.e.:
<current project dir>/node_modules/tns-core-modules
- there's notslib
here, so try the next one<current project dir>/node_modules
- there'stslib
here - use it.
So, the tslib
1.8.0 version will be included in the project. The tslib
package installed in node_modules/tns-core-modules/node_modules/tslib
will never be used.
The two lines causing the issue were added in the resolve.modules
were added to resolve an issue when there's a symlinked plugin, which also have a reference to tns-core-modules
. In this case, when the two lines are missing from webpack.config.js
, tns-core-modules
will be included twice in the vendor.js. This leads to errors when running for Android - currently there can be only one tns-core-modules
version in the application.
To Reproduce
$ tns create myApp --js
$ cd myApp
$ npm i --save --save-exact tslib@1.8.0
// At this point check `node_modules/tslib` - it should be version 1.8.0 and `node_modules/tns-core-modules/node_modules/tslib` - it should be 1.10.0 or later.
$ tns run android
You'll see error from device:
JS: Error: Css styling failed: ReferenceError: __spreadArrays is not defined
Also styles of the app will not be applied.
Expected behavior
Webpack should follow Node.js module resolution and use the local version of a dependency first.
Sample project
Additional context
As a workaround, in case you do not have symlinked plugins, remove the following lines from your the resolve.modules
array in your webpack.config.js file:
resolve(__dirname, "node_modules/tns-core-modules"),
resolve(__dirname, "node_modules"),