I'm new to webpack and I'm trying to understand loaders as well as its properties such as test, loader, include etc.
Here is a sample snippet of webpack.config.js that I found in google.
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
include: [
path.resolve(__dirname, 'index.js'),
path.resolve(__dirname, 'config.js'),
path.resolve(__dirname, 'lib'),
path.resolve(__dirname, 'app'),
path.resolve(__dirname, 'src')
],
exclude: [
path.resolve(__dirname, 'test', 'test.build.js')
],
cacheDirectory: true,
query: {
presets: ['es2015']
}
},
]
}
Am I right that test: /.js$/ will be used only for files with extension .js?
The loader: 'babel-loader', is the loader we install using npm
The include: I have many questions on this. Am I right that anything we put inside the array will be transpiled? That means, index.js, config.js, and all *.js files in lib, app and src will be transpiled.
More questions on the include: When files get transpiled, do the *.js files get concatenated into one big file?
I think exclude is self explanatory. It will not get transpiled.
What does query: { presets: ['es2015'] } do?
In webpack config there are multiple things for configuration, important ones are
entry - can be an array or an object defining the entry point for the asset you want to bundle, can be a js as test here says do it only for /.js$. Your application if has multiple entry points use an array.
include - defines the set of path or files where the imported files will be transformed by the loader.
exclude is self explanatory (do not transform file from these places).
output - the final bundle you want to create. if you specify for example
output: {
filename: "[name].bundle.js",
vendor: "react"
}
Then your application js files will be bundled as main.bundle.js and react in a vendor.js files. It is an error if you do not use both in html page.
Hope it helped
This documentation helped me understand better. Looks like it is for webpack 1 but still applies.
https://webpack.github.io/docs/configuration.html#module-loaders
Loaders
An array of automatically applied loaders.
Each item can have these properties:
test: A condition that must be met
exclude: A condition that must not be met
include: An array of paths or files where the imported files will be transformed by the loader
loader: A string of “!” separated loaders
loaders: An array of loaders as string
This example helped me understand what is going on. Looks like you use either include or exclude but not both. The test is a condition applied to all files. So if you include a folder, each file must pass the test condition. I have not verified this, but based on the example provided by the documentation, it look like that is how it works.
module: {
rules: [
{
// "test" is commonly used to match the file extension
test: /\.jsx$/,
// "include" is commonly used to match the directories
include: [
path.resolve(__dirname, "app/src"),
path.resolve(__dirname, "app/test")
],
// "exclude" should be used to exclude exceptions
// try to prefer "include" when possible
// the "loader"
loader: "babel-loader" // or "babel" because webpack adds the '-loader' automatically
}
]
}
1) Correct.
2) Correct.
3) Correct.
4) I am unsure. My webpack.config.js file includes an output key, and does bundle it all into one file:
output: {
path: path.resolve(__dirname, 'build'),
filename: 'bundle.js'
}
5) Correct.
6) This tells babel-loader what sort of transpile you want it to perform, as well as other compile options. So, for example, if you want it to transpile jsx as well + cache results for improve performance, you would change it to:
query: {
presets: ['react', 'es2015'],
cacheDirectory: true
}
Related
I started from a configuration consisting of both webpack 3 and a similarly old babel version. It can be found in the following repo:
https://github.com/konradmi/react-loadable-ssr-code-splitting
I updated both webpack and babel to their latest versions, as well as all the node modules, and migrated the old configuration accordingly. This issue could stem from any of these.
Once I finished migrating, I noticed all the babel plugins traverse my webpack configs files (which are in a separate nested folder) instead of the actual js source files which are properly processed by webpack. (I verified it by doing some logging inside of the babel plugins).
The result is the same regardless of whether I'm using .babelrc or not.
The webpack config files used to be at the root of the project as you can see in the repo I linked to above, and now they are inside of a nested "config" folder.
At first I thought it might be the cause of this issue, so I tried the following:
Using path.resolve() in the entry point in order to use an absolute path to make sure it wouldn't possibly be re-interpreted by babel from a string relative to who knows where.
Putting the webpack config files back in the root of the project and building from that path.
In all the variations I've tried - webpack always does its job perfectly, while babel is traversing the wrong files. I'm not even sure how it's possible, babel-loader should be traversing the files which it got from the previous webpack rule, which emitted the correct files.
Here's my current Webpack 4 config files concatenated into 1 file and stripped of irrelevant rules and plugins for your convenience:
const webpack = require('webpack')
const path = require('path')
const webpackNodeExternals = require('webpack-node-externals')
module.exports = {
name: 'server',
target: 'node',
externals: [webpackNodeExternals()],
entry: './src/server.tsx',
output: {
filename: 'bundle.js',
chunkFilename: '[name].js',
path: path.resolve(__dirname, '../build')
},
mode: 'development',
stats: 'verbose',
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx']
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
babelrc: false,
presets: [
[
'#babel/env',
{
'targets': {
'browsers': ['last 2 versions']
},
'debug': false
}
],
'#babel/preset-react'
],
plugins: [
'#babel/plugin-syntax-dynamic-import',
'#babel/plugin-proposal-class-properties',
'#babel/plugin-transform-object-assign',
'react-loadable/babel'
]
}
}
]
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader'
}
]
}
]
}
}
I was importing webpack in my server source code, the files babel was going over were webpack imports which I added there in the source code. It couldn't find anything else other than those imports because due to previous rules webpack was exporting a bundle with evals containing the processed code (dev mode settings). The babel plugin wasn't looking for eval statements, so the only thing I could see was the processing of webpack related imports.
I am trying to see if there is a shorter way of running webpack bundles, and also why my loaders do not work.
Here is my code:
module.exports = {
context: path.join(__dirname, 'dist'),
entry: ['./ES6bundle.js', './jQuery.js'],
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist')
}
};
// module: {
// loaders: [{
// test: /\.js?$/,
// exclude: /node_modules/,
// loader: 'babel-loader',
// query: {
// presets: ['env']
// }
// }]
// };
The module.exports works but when I run the loaders I get errors.
My other question is about consolidating multiple entries into one file.
The project I am working on has many JS files, and I was wondering if there was a shortcut for multiple entries. Instead of typing out multiple entries' filenames, can I grab all JS files in the same folder or have a JS file to require them all?
Let me know if this makes sense or not. I am relatively new to programming. Thanks!
Regarding the second part of your question:
can I grab all JS files in the same folder or have a JS file to
require them all
You can have one entry file and in there you do:
module.exports = {
context: path.join(__dirname, 'dist'),
entry: ['./jQuery.js', './allJsFilesOfFolder.js'],
allJsFilesOfFolder.js:
require.context("../scripts/", true, /\.js$/);
This will bundle all scripts inside scripts and all its subfolders.
You need to install #types/webpack-env to have context at your hand.
Specify false if you want to bundle only the scripts in the scripts folder.
You can do the same with other resources like images, you only have to adapt the regex
Copy #Legends comment as answer here.
have no experience with vue files, but as I said you can bundle not only js files, but also image files, for example the regex for image files would be: /.(png|ico|svg|jpg|gif)$/.
I have used webpack ^2.2.1. I have added some loaders In my webpack.config.js file.
But my loader have not call in an order.
I used babel-loader for transform react-es6 codes to react-es5 codes. My custom-loader need react-es6 code. So I put my loader to first. I have print source content in each loaders. But every time first printing babel-loader info. After printing my info.
Is my loader order correct?
Help me! Thanks in advance!
// webpack.config.js
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './build')
}
module: {
loaders: [
{
test: /\.js$/,
use: 'my-custom-loader'
},
{
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['babel-preset-es2015', 'babel-preset-react']
}
}
]
}
]
}
}
Loaders in Webpack are used in order "right to left" so the last loader in your array is used first. Therefore babel is translating everything and your loader is second in line.
See: What is the loader order for webpack?
Try switching the order of your loaders (and of course use module.rules instead of module.loaders, so that you are using the new Pattern in Webpack 2)
I've inherited a web app that uses webpack. In my app, I have a directory called "pub", which looks like this:
./pub
/styles
app.css
/images
brand.png
I have been trying unsuccessfully all morning to use these via webpack. In my webpack.config.js file, I have the following:
const path = require('path');
const projectRoot = path.resolve(__dirname, '../');
module.exports = {
entry: {
app: './src/index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'app.bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192
}
}
]
}
]
}
};
Then, in my index.js file, I have the following:
import logoImage from './public/images/brand.png';
require("css!./public/css/app.css");
When I run webpack, I receive an error that says:
BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders.
You need to specify 'css-loader' instead of 'css',
see https://webpack.js.org/guides/migrating/#automatic-loader-module-name-extension-removed
I don't really understand this error. When I look at it, and then I look at my webpack.config.js file, it looks to me like I'm using css-loader. Beyond that though, how do I use a style in my webpage once the require statement is working. I'm just trying to use webpack with a web app and want to import my brand and CSS and I can't figure it out.
You don't need the css! in your require statement
require("css!./public/css/app.css");
You can just use
require("./public/css/app.css");
Because you are testing files with:
{
test: /\.css$/, // <-- here
loader: "style-loader!css-loader"
},
Or without the rule in your webpack config
// No test in rules matched but you tell webpack
// explicitly to use the css loader
require("style-loader!css-loader!./public/css/app.css");
Your hierarchy is pub/styles/app.css but the location you use in your require is public/css/app.css. It looks like you're trying to call your css from the wrong location.
If this doesn't solve your issue, check out this link https://webpack.github.io/docs/stylesheets.html
The first step on that page is to install css-loader and configure it, this might be a good place to start.
I am trying to build a Webpack custom loader:
module.exports = function(source) {
// Transform the source and return it
console.log('$$$$$$$$$$$$$$$$$$$$$');
return source;
};
Now, I want to use it in my loaders array, something like:
loaders: [
{test: /\.vm$/, loader: 'vm-loader', exclude: [/node_modules/, /dist/]}
]
I tried to use resolveLoader's alias, but it did not work:
resolveLoader: {
alias: {
"vm-loader": path.join(__dirname, "./lib/velocity-plugin")
},
root: [
path.join(__dirname, 'node_modules'),
path.resolve('./node_modules')
]
}
What Am I missing?
Answering my own question:
As it turned out, my custom loader doesn't work because webpack does not work on files which where not required. In my case those html/vm files are not required and not part of the bundle (they are rendered by the server).
My solution was adding gulp in order to have this working. Another (hacky) solution will be using this method