Webpack change import path for a specific package - javascript

Let's assume, we do have few js libs, that installed into our bundle.
And, for some reason, I need to use a library from node_modules of a library.
I can do import it via
import thing from 'somelib/node_modules/thing';
And I want to do just:
import thing from 'thing';
But behind the scenes, webpack will know - the path should be 'somelib/node_modules/thing'
How can I change/override a specific import path in my webpack config file, so my node will bring me a package from the destination that I want?

I think you are looking for resolve.alias
https://webpack.js.org/configuration/resolve/#resolve-alias

In your webpack config, specify the resolve.modules
This example from the webpack documentation adds the "src" folder.
module.exports = {
//...
resolve: {
modules: [path.resolve(__dirname, 'src'), 'node_modules']
}
};
Or if you really don't want this affecting your other entry points, you could create separate webpack configs. (They can still import settings from a primary file) that allows you to set resolve.aliases and resolve.modules independently for each entry point.

Related

How do i have an assets file that i can use in any file in my react app without always having to navigate to the assets folder

How to use import "assets/css/" in any directory within my app
instead of this import "../assets/css/"
It called Absolute Path Imports
If you using create-react-app, create file called .env with following content at the root of your project and restart the dev server and you are good to go:
NODE_PATH=src/
Otherwise add following to webpack.config.js (Module Resolution):
resolve: { modules: [path.resolve(__dirname, './src'), 'node_modules'] };
I think you can use postinstall
It allows you to create aliases for different folders in your app. check it here
I think you should keep your file in the public Folder and then you can try this directly without importing.
Reference:
https://stackoverflow.com/a/63961058/8425297

How does webpack pick a relative path inside node_modules ? does it reference package.json at all?

When i do npm install react-slick, i get the following in my node_modules folder:
Now in my react application in a src/index.js file, when i do the following:
import Slider from "react-slick";
How does webpack know where to pick slider from ? will it at all look for some clue or definition inside node_modules/react-slick/package.json at all ?
Edit :- so here is the package.json file for webpack, when i import Slider from 'react-slick' , does it resolve to dist or lib ? and which file does it pick then and why ?
Well, the simple walkthrough of it will be as below:
Simple Walkthrough
If you carefully look at the node_modules/react-slick/package.json there is a property named main. Something like this:
{
"name": "react-slick",
"main": "index.js"
}
It will tell the Webpack which file is the entry file of the whole package (It's usually referred to index.js). All the necessary exports for the package lies in this file, so Webpack will only look for those exports and will import what you looking for. In this particular case, there should be a default export for the Slider that you using right now. So the index.js is probably something like this:
// index.js
var slider = require('./lib/slider'); // Usually all the main modules are lies under lib folder.
// other imports ...
module.exports = slider;
Difference between lib and dist
Usually, the dist folder is for shipping a UMD that a user can use if they aren't using package management. The lib folder is what package.json, main property points to, and users that install your package using npm will consume that directly. The only use of the lib as opposed to src is to transform your source using babel and Webpack to be more generally compatible since most build processes don't run babel transforms on packages in node_modules.
Webpack uses aliases to target node_modules using a shorthand.
Example #1:
import 'xyz'
/abc/node_modules/xyz/index.js
Example #2:
import 'xyz/file.js'
/abc/node_modules/xyz/file.js
Once it targets the correct folder in node_modules, it follows the rules written in the package itself (manifest, package.json)
You can also define your own aliases as such:
webpack.config.js
const path = require('path');
module.exports = {
//...
resolve: {
alias: {
xyz$: path.resolve(__dirname, 'path/to/file.js')
}
}
};
And then can be used as import xyz from $xyz

javascript better import hook without navigating through relative folders

something which is bothering me when writing tests in my folder structure is the following thing:
//App
meteor/imports/api/tasks.js
//test
meteor/test/imports/api/tasks.test.js
So now when i import something from tasks.js i go like import { task } from '../../../imports/api/tasks.js' and my folder structure gets much bigger than this.
is there a better solution?
I was thinking of an import hook, maybe in the root tests directory, so i can import all the things from there, and when i am on the test, i can import from the import hook and don't have to do all the ../../../../ navigation.
If you are using babel, you can add babel-plugin-module-resolver to your babel configuration.
A Babel plugin to add a new resolver for your modules when compiling
your code using Babel. This plugin allows you to add new "root"
directories that contain your modules. It also allows you to setup a
custom alias for directories, specific files, or even other npm
modules.
The module resolver may collide with webpack2 module handling, so you'll want to limit it just to tests:
.babelrc example:
"env": {
"test": {
"plugins": [
["module-resolver", {
"root": ["./meteor/imports"]
}]
]
}
}
Use
/imports/api/tasks.js
instead of
../../../imports/api/tasks.js
The / to start with marks root.

Resolving javascript files using webpack

My webpack.config.js contains something like:
...
module.exports = {
entry: './app.js',
output: { path: __dirname + "/dist/", filename: 'bundle.js' },
resolve: {
root: path.resolve('./js')
}
....
}
The documentation suggests resolve can have a root value. But I get the error below.
$ node ./node_modules/webpack/bin/webpack.js
Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.resolve has an unknown property 'root'. These properties are valid:
object { alias?, aliasFields?, cachePredicate?, descriptionFiles?, enforceExtension?, enforceModuleExtension?, extensions?, fileSystem?, mainFields?, mainFiles?, moduleExtensions?, modules?, plugins?, resolver?, symlinks?, unsafeCache?, useSyncFileSystemCalls? }
I get the same with modulesDirectories. Not sure which, or if either, I should be using. Any idea how I can pull my JS files in?
You've looked at the documentation for webpack 1. Webpack 2 removed resolve.root and unified it to resolve.modules, as shown in the Migration Guide of the official webpack 2 docs.
The correct way of doing it with webpack 2 is:
resolve: {
modules: [path.resolve('./js'), 'node_modules']
}
But you might have misunderstood what the option does. It does not include all the files in those paths. Webpack starts from your entry point and processes just the files that are being imported (see also Core Concepts). So if you want webpack to include your JavaScript files, you need to import them at some point.
Instead this option tells webpack where to look for the module when you import it (not with a relative path). By default only node_modules is used for resolving Module paths, just like Node.js does it.
For example with this directory structure:
js
├─ components
│  └─ main.js
└─ utils
└─ helper.js
You can import the helper.js file from anywhere in your project with:
import helper from 'utils/helper';
Whereas if you didn't add js/ to the resolve.modules you would need to import it with a relative path. So for instance in js/components/main.js the import would look like this:
import helper from '../utils/helper`;
Obviously the relative path is different depending on which directory you're in.

Webpack resolve.root and TypeScript loader

Our project is using the webpack resolve.root option to import modules with absolute paths. (avoiding something like ../../../module)
In its current state the project is using babel-loader which works perfectly fine.
My task is to migrate the app to Angular 2.
Therefor I am currently in the process of transitioning to TypeScript.
Somehow it seems like the ts-loader does not work in combination with the resolve.root option of the webpack config.
Example of the webpack.config.js
resolve: {
root: [
path.resolve('./node_modules'),
path.resolve('./app'),
path.resolve('./app/lib'),
]
},
Example of a module import
import AbstractListState from 'states/abstract_list_state';
The states directory is inside the app/lib directory.
Error when executing webpack
ERROR in ./app/mainViews/panel/panel.controller.ts
Module not found: Error: Cannot resolve module 'states/abstract_list_state' in C:\Users\...\Project\app\mainViews\panel
# ./app/mainViews/panel/panel.controller.ts 4:28-65
Pre version 2.0 TypeScript will try to load modules with an absolute path from the node_modules directory. This is because TypeScript's module resultion is per default set to "node". Which means it works like node's require method. So, even if you're using webpack to build your app, TypeScript (and its compiler) will still want to load the files.
In order to let webpack import your modules with absolute path you have to go back and use the require method. This way TypeScript will let webpack import stuff. But of course you will not get any type-inference, autocomplete, ...
Or, you update to the TypeScript 2.0 beta and give this a try: https://github.com/Microsoft/TypeScript/wiki/What%27s-new-in-TypeScript#module-resolution-enhancements-baseurl-path-mapping-rootdirs-and-tracing

Categories