1.
Entry instructs webpack to use which file as the starting point to start packaging, analyze and build the internal dependency graph.
2.
Output instructs webpack where to output the packaged resource bundles and how to name them.
3. Loader
webpack can only understand JavaScript and JSON files, which is the built-in capability of webpack available out of the box. Loaders enable webpack to process other types of files and convert them into valid modules that can be used by applications and added to the dependency graph.
4.
PluginsPlugins can be used to perform a wider range of tasks. Plug-ins range from packaging optimization and compression to redefining variables in the environment.
5. Mode
mode (Mode) instructs webpack to use the configuration of the corresponding mode.
Let’s give you a detailed introduction to the five core concepts of webpack.
The entry object is used by webpack to find, start and build the bundle. entry is the starting point of the application. From this starting point, the application starts execution. If you pass an array, each item in the array will be executed. The entry point indicates which module webpack should use to start building its internal dependency graph. After entering the entry point, webpack will find out which modules and libraries the entry point depends on (directly and indirectly).
Simple rule: Every HTML page has a starting point. Single page application (SPA): one entry point, multi-page application (MPA): multiple entry points.
The default value is ./src/index.js
, but you can specify a different entry point (or points) by configuring the entry
attribute in the webpack configuration. For example:
//Single entry--string module.exports = { entry: './path/to/my/entry/file.js', }; //Multiple entries--array module.exports = { entry: ['./src/index.js', './src/add.js'] }; //Multiple entries--object module.exports = { entry: { home: './home.js', about: './about.js', contact: './contact.js' } };
Value type of entry:
string: single entry, packaged to form a chunk, and only one bundle file will be output in the end. The default name of the chunk is the main
array: multi-entry, all entry files will only form one chunk in the end. Output a bundle file, and the chunk name defaults to main. Generally only used in HMR function to make HTML hot update effective
object: multiple entries, as many chunks as there are keys, and as many bundle files are output, and each key (key) will be the name of the chunk. In the object type, the value of each key can also be an array, not just a string
output
instructs webpack how to output and where to output your bundle, asset and other packages you package or Anything loaded using webpack. The default value of the output bundle is ./dist/main.js
, and other generated files are placed in the ./dist
folder by default.
You can configure these processes by specifying an output
field in the configuration:
//webpack.config.js const path = require('path'); module.exports = { entry: './path/to/my/entry/file.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'my-first-webpack.bundle.js', }, };
We can tell webpack the name of the bundle and where the bundle is generated through output.filename
and output.path
properties.
2.1. output.filename (file name and directory)
This option determines the directory and name of each output bundle. These bundles will be written to the directory specified by the output.path
option.
For a single入口
point, filename will be a static name. However, when creating multiple bundles through multiple entry points, code splitting, or various plug-ins, other methods should be used to give each bundle a unique name.
//Single entry: module.exports = { //... output: { filename: 'js/bundle.js' } }; //Multiple entries--use the entry name: module.exports = { //... output: { filename: '[name].bundle.js' } }; //Multiple entries - use a unique hash to generate module.exports = { in each build process //... output: { filename: '[name].[hash].bundle.js' } }; ...
2.2. output.path (file directory)
output.path specifies the directory of all output files, which is the common directory for all future resource output. path must be an absolute path.
module.exports = { //... output: { path: path.resolve(__dirname, 'dist/assets') } };
2.3. output.publicPath (path prefix of referenced resources)
publicPath specifies the public path prefix introduced by all resources in the html file. It does not affect the path of the generated file. Instead, when the html file introduces various resources, publicPath is added as a prefix to the path of the imported resources.
Example:
In the webpack configuration generated by vue-cli, the value of publicPath in the production environment defaults to '/', which is the root directory of the current directory.
After packaging, we open the html file and we can see that the resource path introduced in the html file is:
As you can see, the / symbol is added in front of the path. When we open the browser to access the generated html file, we will find an error. The resource cannot be accessed and a 404 report is reported. At this time, the resource access is similar to the following:
It may be as follows on the server, but there may be problems accessing it.
We can change publicPath to a relative path, or comment it out directly.
2.3.1. The difference between path and publicPath.
打包后文件在硬盘中的存储位置,是webpack所有文件的输出的路径,必须是绝对路径。比如:输出的js、图片,HtmlWebpackPlugin生成的html文件等,都会存放在以path为基础的目录下。
2.4. output.chunkFilename (name of non-entry chunk)
output.chunkFilename determines the name of the non-entry chunk file. That is, in addition to the chunks generated by the entry file, the chunk files generated by other files are named.
module.exports = { //... output: { chunkFilename: 'js/[name]_chunk.js' //The name of the non-entry chunk} };
webpack itself can only package JavaScript and JSON files ( webpack3+和webpack2+
have built-in processing of JSON files, but webpack1+并不支持,
needs to introduce json-loader
). This is the built-in capability of webpack available out of the box. Webpack itself does not support packaging other types of files, such as CSS, Vue, etc., but we can use various loaders to let webpack process these types of files. The loader can convert files from different languages (such as TypeScript) to JavaScript or convert inline images into data URLs. The loader even allows you import
CSS files directly in JavaScript modules!
By using different loader
, webpack
has the ability to call external scripts or tools to process files in different formats, such as analyzing and converting scss to css, or converting next-generation JS files (ES6, ES7) to modern browsers Compatible JS files. For React development, appropriate Loaders can convert JSX files used in React into JS files.
In the webpack configuration, loader has two attributes:
test
attribute, which identifies which files will be converted.
The use
attribute defines which loader should be used when performing conversion.
include/exclude(可选):
manually add files (folders) that must be processed or block files (folders) that do not need to be processed
query(可选)
: provide additional setting options for loaders
// Example: webpack.config. js const path = require('path'); module.exports = { output: { filename: 'my-first-webpack.bundle.js', }, module: { rules: [ { test: /.txt$/, loader: 'raw-loader' }, { test: /.css$/, use: ['style-loader', 'css-loader'] } //If you use multiple loaders, you should use use ], }, };
In the above configuration, the rules
attribute is defined for a separate module object, which contains two required attributes: test
and use
. This is equivalent to telling the webpack compiler that when it encounters a path that is parsed as '.txt' in the require()
/ import
statement, use raw-loader
to convert it before packaging it.
If you use multiple loaders, you should use use. The loaders in the use array are executed in order: from right to left, in sequence. For example, in the above css file, first css-loader will compile the css file into JS and load it into the JS file. Then style-loader will create a style tag and insert the style resources in JS into the head tag.
3.1. CSS-loader
Webpack provides two tools for processing style sheets, css-loader
and style-loader
. They handle different tasks. css-loader
enables you to introduce css files using a method similar to import
. style-loader
adds all calculated styles to the page. The combination of the two allows you to embed style sheets into JS files packaged by webpack. From this, the css file can be introduced into the JS file.
//Install npm install --save-dev style-loader css-loader //If the css-loader version is too high, compilation may go wrong. It is recommended to lower the version such as [email protected] available
//Use module.exports = { ... module: { rules: [ { test: /(.jsx|.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ }, { test: /.css$/, //How to introduce multiple loaders to the same file. The order of action of loaders is that the later loaders start to act first use: [ { loader: "style-loader" }, { loader: "css-loader" } ] } ] } };
Assume there is a main.css file:
body { background: green; }
In order for webpack to find the "main.css" file, we import it into "main.js", as follows:
//main.js import React from 'react'; import {render} from 'react-dom'; import Greeter from './Greeter'; import './main.css';//Use require to import the css file render(<Greeter />, document.getElementById('root'));
Normally, css will be packaged into the same file as js, not Will be packaged as a separate css file. However, with appropriate configuration webpack can also package css into separate files.
loaders are used to convert certain types of modules, while plug-ins can be used to perform a wider range of tasks, including: packaging optimization, compression, resource management, injecting environment variables, etc. The purpose of the plug-in is to solve other things that the loader cannot achieve.
To use a plugin, we need to install it via npm
and then add an instance of the plugin under the plugins property. Since plugins can carry parameters/options, you must pass the new
instance to plugins
property in the webpack configuration. Most plug-ins can be customized through options, and you can use the same plug-in multiple times for different purposes in a configuration file.
//webpack.config.js const HtmlWebpackPlugin = require('html-webpack-plugin'); // Install via npm const webpack = require('webpack'); // Used to access built-in plug-ins module.exports = { module: { rules: [{ test: /.txt$/, use: 'raw-loader' }], }, plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })], };
In the above example, html-webpack-plugin
generates an HTML file for the application and automatically injects all generated bundles.
4.1. BannerPlugin plug-in (adding copyright statement)
Below we have added a plug-in that adds a copyright statement to the packaged code. This plug-in is a built-in plug-in in webpack and does not need to be installed.
const webpack = require('webpack'); module.exports = { ... module: { rules: [ { test: /(.jsx|.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ }, { test: /.css$/, use: [ { loader: "style-loader" }, { loader: "css-loader", options: { modules: true } }, { loader: "postcss-loader" } ] } ] }, plugins: [ new webpack.BannerPlugin('Wenxuehai All Rights Reserved, Any Reproduction Will Be Investigated') ], };
4.2. Hot Module Replacement plug-in (hot loading)
Hot Module Replacement
(HMR) is a very useful plug-in in webpack. It allows you to automatically refresh and preview the modified effect in real time after modifying the component code. Hot loading is different from webpack-dev-server. When the application is running, hot replacement can view the effect of code updates without refreshing the page, just like modifying the dom style directly on the browser, while webpack-dev-server requires Refresh the page.
(1) Add the HMR plug-in to the webpack configuration file;
(2) Add the "hot" parameter to the Webpack Dev Server;
4.2.1. React implements hot loading
. React modules can use Babel to implement hot loading of functions. Babel has a plug-in called react-transform-hrm
, which allows HMR to work properly without additional configuration of the React module;
install react-transform-hmr
npm install --save-dev babel-plugin-react-transform react -transform-hmr
const webpack = require('webpack'); module.exports = { entry: __dirname + "/app/main.js",//The only entry file that has been mentioned many times output: { path: __dirname + "/public", filename: "bundle.js" }, devtool: 'eval-source-map', devServer: { contentBase: "./public",//The directory where the page loaded by the local server is located historyApiFallback: true,//Do not jump inline: true, hot: true }, module: { rules: [ { test: /(.jsx|.js)$/, use: { loader: "babel-loader" }, exclude: /node_modules/ }, { test: /.css$/, use: [ { loader: "style-loader" }, { loader: "css-loader", options: { modules: true } }, { loader: "postcss-loader" } ] } ] }, plugins: [ new webpack.BannerPlugin('Copyright, any reproduction will be investigated'), new webpack.HotModuleReplacementPlugin() //Hot reload plug-in], };
Configure Babel
// .babelrc { "presets": ["react", "env"], "env": { "development": { "plugins": [["react-transform", { "transforms": [{ "transform": "react-transform-hmr", "imports": ["react"], "locals": ["module"] }] }]] } } }
//Greeter,js import React, { Component } from 'react' import styles from './main.css' class Greeter extends Component { render() { return ( <div> <h1> aaaf </h1> </div> ); } } export default Greeter
//main.js import React from 'react'; import { render } from 'react-dom'; import Greeter from './greeter.js'; render( < Greeter / > , document.getElementById('root'));
Now if we can implement hot loading module, we can see the updated content directly on the browser every time we save, and the browser does not need to refresh. Automatically refresh.
(Sometimes there is no effect, it may be a version problem)
4.3. ExtractTextWebpackPlugin plug-in (extracting css).
By default, webpack will not treat the css style as an independent file, but will also package the css into a js file and package the generated When the js file is rendered, the style will be inserted into the page in the form of style tag through js syntax. But in this case, the packaged bundle file may be too large. At this time, we can use the ExtractTextWebpackPlugin plug-in to separate the css style into a css file.
The ExtractTextWebpackPlugin plug-in will move the *.css referenced in the entry chunk (including the imported css file and the style written in the vue file) to an independent and separated CSS file. ExtractTextPlugin
will generate a corresponding css file for each entry chunk, which means that one entry corresponds to a css file. If there are multiple entries, multiple corresponding css files will be generated respectively.
With the ExtractTextWebpackPlugin plug-in, your styles will no longer be embedded in the JS bundle, but will be placed in a separate CSS file (ie styles.css
). If your style files are larger in size, this will make early loading faster because the CSS bundle will be loaded in parallel with the JS bundle.
const ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { module: { rules: [ { test: /.css$/, use: ExtractTextPlugin.extract({ fallback: "style-loader", use: "css-loader" }) } ] }, plugins: [ new ExtractTextPlugin({ filename: utils.assetsPath('css/[name].[contenthash].css'), //ExtractTextPlugin generates a corresponding file for each entry chunk, so when you configure multiple entry chunks, you must use [ name], [id] or [contenthash] // allChunks: true, // When using `CommonsChunkPlugin` and there are extracted chunks (from `ExtractTextPlugin.extract`) in the common chunk, `allChunks` ** must be set to `true`. }), ] }
4.3.1. allChunks option (whether to also extract asynchronously loaded styles together)
The default value of the allChunks option of the ExtractTextWebpackPlugin plug-in is false.
The allChunks option means whether asynchronously loaded styles need to be extracted together. Because by default, even if the ExtractTextWebpackPlugin plug-in is used, if the style or style file is loaded asynchronously, these styles will not be extracted into independent css files, but will still be packaged into js files.
Therefore, allChunks:false
is the default value. The default value is to extract the code from the entry, but the asynchronously loaded code will not be extracted; allChunks:true
is to extract the code of all modules (including asynchronously loaded modules) into a file. If asynchronous loading of styles is used, but allChunks is set to false, then we need to set the fallback of ExtractTextPlugin.extract. fallback
is to use style-loader
to load asynchronously when the css code loaded by the asynchronous code is not extracted. The style of the component.
Please refer to:
https://github.com/sevenCon/blog-github/blob/master/articles/webpack study notes (2)-Usage of ExtractTextWebpackPlugin.md
https://blog.csdn.net/weixin_41134409/article/details /88416356
By selecting one of development
, production
or none
to set mode
parameter, you can enable webpack's built-in optimization in the corresponding environment. Its default value is production
.
module.exports = { mode: 'production', };
Configuring the mode option directly in the configuration file will tell webpack to use the built-in optimization of the corresponding mode. The mode options include development, production, and none.
development: development mode, the packaged code will not be compressed, and code debugging is enabled.
production: production mode, just the opposite.
Set the mode to development or production, and webpack will automatically set the value of process.env.NODE_ENV. We can get this value directly in any folder. But if you only set NODE_ENV
, mode
will not be set automatically. (In node, the global variable process represents the current node process. The process.env attribute contains user environment information. The NODE_ENV attribute does not exist in process.env itself. We generally define the NODE_ENV attribute ourselves and use it to Determine whether it is a production environment or a development environment)
(Please note: the mode option is new in webpack4. Before 4, it was set with the DefinePlugin plug-in. Webpack4 deleted the DefinePlugin)
5.1. The mode configuration of the vue-cli project is explained in detail
in webpack. Generally, The value of NODE_ENV will be configured in the configuration file. In the vue project generated by default using vue-cli, the NODE_ENV configuration is as follows:
//Under the webpack.dev.conf.js file, the dev.env.js file is introduced new webpack.DefinePlugin({ 'process.env': require('../config/dev.env') }),
//module.exports = merge(prodEnv, { in dev.env.js file NODE_ENV: '"development"' }) //
Under the webpack.prod.conf.js file, the prod.env.js file is introduced const env = require('../config/prod.env') new webpack.DefinePlugin({ 'process.env': env }),
//module.exports = { in prod.env.js file NODE_ENV: '"production"' }
As you can see from the above, in the development environment, the configuration file configures NODE_ENV to 'development'; in the production environment, the configuration file configures NODE_ENV to 'production'.
When we run the project, we will execute npm run dev or npm run build. These two commands use the configuration file of the development environment or production environment to generate the running project, and accordingly configure the corresponding NODE_ENV value. We In other words, the corresponding NODE_ENV value can be obtained in any file of the project (not necessarily the configuration file, because it depends on whether the configuration file configured with the NODE_ENV value has taken effect).
5.2. Process.env.NODE_ENV configuration
process is a global variable of node, and process has the env attribute, but does not have the NODE_ENV attribute. The NODE_ENV variable is not directly available in process.env, but is obtained by setting it. However, NODE_ENV
variable is usually used to define the environment type. The function of this variable is: we can distinguish the development environment or the production environment by judging this variable.
(1) Global variable values can be set through webpack’s built-in plugin DefinePlugin:
new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }),
after setting, you can get this value in the execution script, for example:
// main.js console.log(process.env.NODE_ENV); //production
but this value cannot be obtained in the webpack configuration file webpack.config.js.
(2) First download the cross-env package through the
cross-env package setting:
cnpm i cross-env -D
Set the package.json file:
"build": "cross-env NODE_ENV=test webpack --config webpack.config.js"
At this time, the value (process.env.NODE_ENV) can be obtained in the configuration file, but cannot be obtained in the executable script. It needs to be used with the DefinePlugin plug-in.