NativeScript / nativescript-dev-webpack

A package to help with webpacking NativeScript apps.
Apache License 2.0
97 stars 49 forks source link

Webpack always resolves packages from the root of node_modules #1037

Open rosen-vladimirov opened 5 years ago

rosen-vladimirov commented 5 years ago

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):


**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](https://github.com/NativeScript/nativescript-dev-webpack/blob/2978b81b5a8100774b2bb4a331ac8637205927b8/templates/webpack.javascript.js#L97-L102). 
According to [webpack's documentation](https://webpack.js.org/configuration/resolve/#resolvemodules):

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 no `tslib` here, so try the next one
* `<current project dir>/node_modules` - there's `tslib` 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](https://github.com/NativeScript/nativescript-dev-webpack/blob/2978b81b5a8100774b2bb4a331ac8637205927b8/templates/webpack.javascript.js#L98-L99) 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**
<!-- If possible, consider attaching a sample project or link to a repository with such 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:
```JavaScript
resolve(__dirname, "node_modules/tns-core-modules"),
resolve(__dirname, "node_modules"),
romandrahan commented 5 years ago

Same for me.

marklanhamhc commented 4 years ago

I have a similar issue: https://github.com/NativeScript/nativescript-angular/issues/1983

romandrahan commented 4 years ago

Was able to resolve it with @marklanhamhc's workaround.