Webpack, change node_modules lookup order - javascript

In my project (project A) I have a webpack alias to the directory in the neighboring project (project B, outside of the project A directory). Both of them have own node_modules.
When in project A I import some file from project B that has an import of some library then it still gets imported from projectB/node_modules. I want this to be imported from projectA/node_modules.
- projectA
- src/file1.ts (imports 'dirB/file2' from project B, which leads to 'react' library for 'file2' to be imported from project B)
- dirB (webpack alias to 'projectB/dir')
- node_modules/react
- projectB
- dir/file2.ts (imports 'react' library)
- node_modules/react
A solution that I see it to tell webpack that for files in projectB start node_modules resolution as if they were located in projectA somehow. How can I achieve this?
I know this is a dirty setup and I really should do packages/npm link, but this is how it is, I just want to temporarily reuse some files within projectB but without copypasting them (but the result should be as if I did copypaste). Tried creating a symlink instead of webpack alias - the issue remains the same.

Related

npm package contains more than one file - how to umport these

I've a npm package with the following three files in the dist folder (generated by webpack):
Inside the package.json file I've declated the sample.js file as the main one: "main": "dist/sample.js",.
Now I wan't to use this package in another project. Did I need to import all three files? Or should all work fine with one import like import aFunction from 'package-name'?
If there aren't any other weird dependencies, and sample.js is actually the entrypoint of the library (i.e. either you do everything inside it, or you make all the needed exports from it), it should work fine just as you wrote, i.e. import aFunction from 'package-name'.
Btw, is sample.js minified? As far as I remember, starting with Webpack v4 it does the minification automatically for production builds. But you might still want to doublecheck (read here for more info).

How do NPM Package imports resolve?

I have a monorepo with lerna, yarn workspaces, and the following structure:
- packages
- a_webpack
- src
- index.ts
- dist
- main.js
- main.css
- b_tsc
- src
- indes.ts
- dist
- index.js
both packages a_webpack and b_tsc are to be consumed by another package c.
on b_tsc i run tsc to compile into its dist folder.
on a_webpack i run webpack to do the same
I mainly use webpack, because I can get a separate .css file in the dist that can be imported
When I import b_tsc in package c like:
import { something } from 'b_tsc'
everything works as expected.
Also when I do:
import 'b_tsc/dist/main.css'
that is working.
However when i try:
import { something } from 'a_webpack'
I'm getting:
Module not found: Can't resolve 'a_webpack'
Question
Even if I change the output of webpack to generate dist/index.js, it doesn't work. What am I doing wrong here?
General Question
When importing like seen above, how does the compiler know it needs to look inside dist/main.js or any other entry point within that package?
Figured it out:
The entrypoint is specified in the package.jsons main property.
That solved the import issue for me.

Problems using "index.js" to import ES6 JS Modules

I'm working with React Native and using index.js to manage modules. I have many projects consuming from the same components folder, which has a structure like this:
components
|_ComponentOne.js
|_ComponentTwo.js
|_index.js
In which the index.js looks like this:
export * from './ComponentOne.js';
export * from './ComponentTwo.js';
Now lets say I have three projects:
ProjectOne, which uses ComponentOne;
ProjectTwo, which uses ComponentTwo;
ProjectThree, which uses both;
Every project has its own files, but they refer to this same folder to use components (like a shared assets folder). Everything works fine while all the projects have all dependencies for all components.
In another words, I have a problem when one of the projects doesn't install a dependency for one of the components, even when the project doesn't uses that component.
Let's take as an example ProjectOne, which uses only ComponentOne. If ComponentTwo (which is not used in this project) has dependency X, I have to npm install dependency X even on ProjectOne, or an error is given. Again, ProjectOne doesn't use dependency X.
I can only image this happens because the index.js validates all declared exports, even when they're not used.
I'm trying to find an alternative to not be forced to install plugins and other things that I won't even use in my projects. I know that if I remove the index.js and start importing files directly on projects, it will work, but I would like to keep the index.js structure (to be able to use multi import syntax import { ComponentOne, ComponentTwo } from 'components').
Any suggestion?
Update:
The error I get, when I do not npm install dependency X is
Module `X` does not exist in the Haste module map
If I install it, everything works.
I'm using the terminal to install the application directly into an android phone. The JS bundle is automatically created by Metro (RN default).

Applying loaders to files imported via resolve.modules in webpack

I have two javascript projects in separate directories within a parent directory and I want both of them to be able to import files from a common directory. The structure looks a bit like this:
- parentDir
- project1
- package.json
- webpack.config.js
- src
- index.js
- project2
- package.json
- webpack.config.js
- src
- index.js
- common
- components
- CommonComponent.vue
- application
- app.js
I'd like both project1's index.js and project2's index.js to be able to import CommonComponent.vue and app.js.
Currently this works if I do:
import CommonComponent from ../../common/components/CommonComponent.vue
However those import paths starts to get very messy and hard to maintain the deeper into each tree we go, with huge numbers of ../s, so I'm trying to find a way of making the imports neater and easier to manage and I came across resolve options in webpack. So I've tried adding this to my webpack.config.js:
resolve: {
modules: [
path.resolve("../common/"),
path.resolve("./node_modules")
]
},
so then the import would look like:
import CommonComponent from "components/CommonComponent.vue"
import app from "application/app"
Importing the plain js file works, but when trying to import the .vue file, webpack throws an error:
ERROR in C:/parentDir/common/components/CommonComponent.vue
Module not found: Error: Can't resolve 'vue-style-loader' in 'C:/parentDir/common/components'
So how can I apply webpack loaders to files imported via resolve.modules?
Note: importing .vue files from within a single project works fine, so my module.rules config is correct.
It turns out the common package needed its own node_modules. That doesn't seem to be the case when importing a file from there directly via its path, but it is when using either resolve.modules or resolve.alias in webpack.
So the answer was to npm init in common and then to npm install all the dependencies and devDependencies needed there. e.g (of course these will depend on the project):
npm install --save vue
npm install --save-dev babel-core babel-loader css-loader less-loader vue-loader vue-template-compiler webpack
Once that's done, both of these webpack configs seem to have the same result as far as I can tell:
resolve: {
modules: [
path.resolve("../../common"),
path.resolve("./node_modules")
]
},
and
resolve: {
alias: {
components: path.resolve("../../common/components")
}
}
Both allow a file in project1 or project2 to do an import like:
import CommonComponent from "components/CommonComponent.vue"

Webpack / NPM: Use build version of installed module instead of re-building from source

I would like to use the dat.GUI library for a project that's build with Webpack 2. If I install the module via npm -install --save-dev dat.gui and then try to import it using import * as DAT from 'dat.gui'; I get the following error when Webpack is trying to compile my project:
ERROR in ./~/dat.gui/src/dat/controllers/NumberControllerSlider.js
Module not found: Error: Can't resolve 'style' in
'/home/me/myProject/node_modules/dat.gui/src/dat/controllers'
BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix
when using loaders.
I know this error occurs when using Webpack 2 to build Webpack 1 based projects. But why is Webpack even trying to build the module if there already is a build version inside node_modules/dat.gui/build';? Is there a way to tell Webpack or NPM to use the existing build version without trying to re-build it?
When importing a node module, webpack looks into its package.json and uses the main field as entry of the module, similar to what Node.js does (webpack looks for more fields by default, see resolve.mainFields).
Since for dat.gui the main field does not point to the built version but to the source, which actually inlines loaders as seen in dat.gui#0.6.1 - NumberControllerSlider.js for the styleSheet import, and that is not a good idea in general and certainly not to publish.
But you can import the built version by specifying the corresponding path. So your import would be:
import * as DAT from 'dat.gui/build/dat.gui.js';
If you'd like to still import just dat.gui you can configure resolve.alias to point to the built version as follows:
resolve: {
alias: {
'dat.gui': 'dat.gui/build/dat.gui.js'
}
}
With that you can use your original import statement:
import * as DAT from 'dat.gui';

Categories