A concept,
Webpack is a __ static module packaging tool __ for modern JavaScript applications. When WebPack works with an application, it internally builds a dependency graph that maps to each module required for the project and generates one or more bundles.
Second, the start
Create the webpack-demo-main folder.
CD webpack-demo-main // go to the file directory NPM init -y // NPM initialization -y means yes. NPM install webpack webpack-cli --save-devCopy the code
Open the package.json file in the project directory and expand it as follows:
{
"name": "webpack-demo-main"."version": "1.0.0"."description": ""."main": "index.js"."scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": []."author": ""."license": "ISC"
}
Copy the code
In this file, we add the private: true parameter, which is to ensure private. Remove the main argument. Now we will create the following directory structure, files, and content:
webpack-demo-main
|- package.json
+ |- index.html
+ |- /src
+ |- index.js
Copy the code
index.js
//index.js
function comp() {
const el = document.createElement('div');
el.innerHTML = '< I > Hello X1AXX1A
'
return el;
}
document.body.appendChild(comp());
Copy the code
index.html
<! DOCTYPEhtml>
<html>
<head>
<meta charset="utf-8" />
<title>X1AXX1A</title>
</head>
<body>
<script src="./src/index.js"></script>
</body>
</html>
Copy the code
Manage resources
3.1 Configuring inlet and Output
Create the webpack.config.js file in the project root directory and enter the following code:
//webpack.config.js
const path = require('path');
module.exports = {
mode: 'development'.// Development environment, production mode
entry: './src/index.js'.// Import file
output: {
filename: '[name].[contenthash].js'.// Output file
path: path.resolve(__dirname, 'dist'),// Output file storage address}};Copy the code
The Entry property sets the project’s entry file output to indicate how and where WebPack should output your “bundles, assets, and anything else you package or load with WebPack.” | – filename Settings of the output file name | – path output file storage directory.
inNode.js
,__dirname
Always points to theThe js file being executedThe absolute path to.
Let’s print it in the webpack.config.js file__dirname
Look, this is the absolute path to the current webpack.config.js.
The path.resolve method resolves a sequence of paths or path fragments to absolute paths. A given sequence of paths is processed from right to left, with each subsequent path appended to the front until an absolute path is constructed.
path.resolve('/ directory 1/ directory 2'.'3'/directory);
// Return: '/ directory 1/ directory 2/ directory 3'
path.resolve('/ directory 1/ directory 2'.'/ directory 3/ directory 4/');
// Return: '/ directory 3/ directory 4'
Copy the code
The path.join method concatenates all the given path fragments together (using platform-specific delimiters as delimiters) and normalizes the generated path. If the connected path string is a zero-length string, a ‘.’ is returned, indicating the current working directory.
path.join(Directory '/ 1'.Directory '2'.'Directory 3/ Directory 4'.Directory '5'.'.. ');
// Return: '/ directory 1/ directory 2/ directory 3/ directory 4'
Copy the code
We’ll create a new dist directory, move index.html to dist, and change the script import path
//index.html
//<script src="./src/index.js"></script>
<script src="main.js"></script>
Copy the code
The script commands are defined in the scripts field of the package.json file.
/ /...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"."build": "webpack"
},
/ /...
Copy the code
Then perform
npm run build
Copy the code
There is an extra main.js file in the dist folder.
3.2 load CSS
To import a CSS file from a JavaScript module, you need to install style-loader and CSS-loader and add these loaders to the Module configuration.
npm install --save-dev style-loader css-loader
Copy the code
Then add the following code to webpack.config.js:
const path = require('path');
module.exports = {
entry: './src/index.js'.output: {
filename: '[name].[contenthash].js'.path: path.resolve(__dirname, 'dist'),},module: {
rules: [{test: /\.css$/i,
use: ['style-loader'.'css-loader'],},],},};Copy the code
The module loader can be called in chain mode. Each loader in the chain will transform the resource. The chain is executed in reverse order. The first loader passes its results (converted resources) to the next loader, and so on. Finally, Webpack expects the last loader in the chain to return JavaScript.
Therefore, ensure the sequence of loader: Style-loader is first, and CSS-loader is last. If this convention is not followed, WebPack may throw an error.
Css-loader will process the content imported by import require() @import URL and convert it into A JS object.
Let’s first remove style-loader and do a test. Try importing a CSS file from index.js and then printing it out. The style we printed out is converted into a JS array by CSS-Loader. As shown below: Modify index.js
import style from './index.css'
function comp() {
const el = document.createElement('div');
el.innerHTML = '< I > Hello X1AXX1A
'
console.log(style)
return el;
}
document.body.appendChild(comp());
Copy the code
The index. CSS file is added in the same directory
div {
color: red
}
Copy the code
Because style prints out an array, the page cannot be used directly. You can see that the font does not turn red.
Next we add the style-loader back. Rerun, the font is red. So style-loader basically adds the array generated by CSS-loader to js.
3.3 Loading Images
Webpack 5 can use built-in Asset Modules, which allow you to use resource files (fonts, ICONS, etc.) without having to configure an extra loader.
Before WebPack 5, commonly used:
raw-loader
Import the file as a stringurl-loader
Inline the file as a data URI into the bundlefile-loader
Send the file to the output directory
Asset Module Type, which replaces all of these Loaders by adding four new module types.
asset/resource
Send a separate file and export the URL. Previously by usingfile-loader
The implementation.asset/inline
Export the data URI of a resource. Previously by usingurl-loader
The implementation.asset/source
Export the source code of the resource. Previously by usingraw-loader
The implementation.asset
Between exporting a data URI and sending a separate fileAutomatic selection. Previously by usingurl-loader
And configure the resource volume limitation implementation.
So all we need to do is add the following code.
{
test: /\.(jpe? g|png|gif|svg)$/i,
type: 'asset'.// Automatically choose between exporting a data URI and sending a separate file
}
Copy the code
See the official Asset Modules tutorial for details
3.4 Resolve (Resolve)
Common examples are alias, extensions resolve. Alias creates an alias for import or require to make module introduction easier. For example, some common modules in the SRC/folder create assets under SRC, store an image, and then import an image in index.js with this option.
import imgSrc from '@/assets/img.png'
Copy the code
Resolve. extentions attempts to resolve these file suffixes in order, that is, there is no need to write the file suffixes when importing the file. Webpack will resolve the file in the order of the configured file suffixes.
module.exports = {
/ /...
resolve: {
extensions: ['.vue'.'.js'].// Indicates that the file suffix can be omitted when importing files
alias: {
The '@': path.join(__dirname, 'src')
// The alias configuration here must be consistent with the Paths alias in jsconfig
// Import files in SRC component can be written @/component/...}},/ /...
}
Copy the code
However, when using alias, you may find that the intelligent hints for paths and functions are missing, and that it is easy to miswrite and inconvenient if path names are complex.
Add jsconfig.json to the root directory
{
"compilerOptions": {
"baseUrl": ". /".// Base directory for resolving non-relative module names
"paths": {
"@ / *": ["src/*"] // Specify the path map to calculate the alias relative to the baseUrl option
},
"experimentalDecorators": true Provide experimental support for the ES decorator proposal
},
"exclude": ["node_module"."dist"]}Copy the code
Note: If the configuration file is tsconfig.json when the project integrates TypeScript, set allowJs: true to jsconfig.json.
3.5 Converting ES6+ to ES5
In order to be compatible with most browsers, you need to parse the JS syntax into ES5 version. A third party loader called Babel helps Webpack handle ES6+ syntax.
3.5.1 track ofBabelWhat is it?
Babel is a JavaScript compiler
Babel is a toolchain for converting ECMAScript 2015+ version code into backwardly compatible JavaScript syntax so it can run in current and older versions of browsers or other environments.
Babel-loader allows you to translate JavaScript files using Babel and Webpack.
Install dependency packages
npm i -D babel-loader @babel/preset-env @babel/core
Copy the code
A major change with @ Babel 7, the original babel-XX package was moved to the Babel domain
@babel-core
The core functions of Babel are contained in the @babel/core module@babel/preset-env
Load the transformation plug-in for functionality not available in the target browser
webpack.config.js
/ /...
rules: [{test: /\.js$/,
exclude: /node_modules/,
use: ['babel-loader']}]/ /...
Copy the code
Create the. Babelrc file in the root directory
{
"presets": [["@babel/preset-env"]]}Copy the code
Add some code to index.js
// Babel tests console.log([1,2,3].findindex (x => x === 4)) console.log(' ABC '.padstart (10))Copy the code
The arrow function was converted, indicating success.
@babel/preset-env provides a useBuiltIns parameter, and when set to Usage, only polyfills needed by the code will be included. Note that to set this parameter to usage, corejs must be set at the same time (warning will be given if not set, default is “corejs”: 2). Note: Here you still need to install @babel/polyfill(the current @babel/polyfill version installs “corejs”: 2 by default)
First of all, the reason for using core-js@3 is that no new features are added to the core-js@2 branch. New features are added to core-js@3. For example, if you’re using array.prototype.flat (), if you’re using core-js@2, it doesn’t include this new feature. In order to use more of the new features, we recommend that you use core-js@3.
npm install --save @babel/polyfill core-js@3
Copy the code
//.babelrc
{
"presets": [["@babel/preset-env", {
"useBuiltIns": "usage"."corejs": 3}}]]Copy the code
3.5.2 @ Babel/plugin – transform – runtime
Babel uses very small helper code for some public methods, such as _extend / _classCallCheck. By default, it is added to every file that needs it. This can lead to repeated imports, which can be solved by @babel/ plugin-transform-Runtime.
The @babel/ plugin-transform-Runtime is usually only used in development, but the runtime relies on @babel/ Runtime, so @babel/ Runtime must be installed as a production dependency.
NPM i-d@babel /plugin-transform-runtime NPM i-d@babel /runtime //Copy the code
Add a line of configuration after the Presets
//.babelrc
{
"presets": [["@babel/preset-env", {
"useBuiltIns": "usage"."corejs": 3}]],"plugins": [
"@babel/plugin-transform-runtime"]}Copy the code
To avoid global contamination, we used the @babel/runtime-corejs3 dependency and modified the configuration file
npm install @babel/runtime-corejs3 --save
Copy the code
//.babelrc
{
"presets": [["@babel/preset-env"]],"plugins": [["@babel/plugin-transform-runtime", {
"corejs": 3}}]]Copy the code
4. Manage output
In our test example above, the generated main.js had to be imported manually in index.html. However, as your application grows, and once you start using Contenthash in file names and exporting multiple bundles, it becomes difficult to continue manually managing index.html files.
This is where the HtmlWebpackPlugin comes in
npm install --save-dev html-webpack-plugin
Copy the code
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
/ /...
plugins: [
new HtmlWebpackPlugin({})
],
module: {
/ /...
Copy the code
HtmlWebpackPlugin will generate a new index.html file, replacing our original file.
Next we create a new public folder in the root directory, move index.html from dist to the public folder, and modify the webpack.config.js file
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
/ /...
plugins: [
new HtmlWebpackPlugin({
title: 'I am the title of the webpack.config configuration'.template: './public/index.html'.HTML / / compression
minify: {
removeComments: true.// Remove comments from HTML
collapseWhitespace: true // Remove whitespace and newline characters}})].module: {
/ /...
Copy the code
This indicates that the index. HTML reference template under public is used. Dynamically introduce compiled related service resources. To configure the title attribute in the configuration file, we need to modify the title in the HTML file to get the configuration option. As follows:
<! --index.html-->
<! DOCTYPEhtml>
<html>
<head>
<meta charset="utf-8">
<title><%= htmlWebpackPlugin.options.title %></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
</body>
</html>
Copy the code
Since WebPack generates files and places them in the /dist folder, it does not keep track of which files are actually used in the project, resulting in many extra files in the DIST. In this case, it is necessary to use the clean-webpack-plugin to empty the Dist folder before creation
npm install --save-dev clean-webpack-plugin
Copy the code
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
/ /...
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'I am the title of the webpack.config configuration'.template: './public/index.html'.HTML / / compression
minify: {
removeComments: true.// Remove comments from HTML
collapseWhitespace: true // Remove whitespace and newline characters}})].module: {
/ /...
Copy the code
5. Development environment
5.1 hot update
Running the NPM run build manually every time the code is compiled can be cumbersome. The Webpack-dev-server plug-in solves this problem.
Webpack-dev-server provides two main functions
- Provide web services for static files
- Auto Refresh and Hot replace (HMR)
Automatic refresh means that current changes to the Webpack are compiled automatically, and hot replacement means that various modules are updated at run time, that is, partial refresh
npm install --save-dev webpack-dev-server
Copy the code
webpack.config.js
module.exports = {
/ /...
devServer: {
contentBase: './dist'
},
/ /...
}
Copy the code
The above configuration tells webpack-dev-server to serve the files in dist to localhost:8080. (Serve as server accessible file)
Webpack-dev-server is not written to any output files after compilation. Instead, you keep the bundle files in memory and then serve them to the server as if they were real files mounted on the server root path. If your page wants to find the bundle files in a different path, you can change this using the publicPath option in the Dev Server configuration.
Modify package.json to add running code
{
/ /...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"."dev": "webpack serve --open chrome"."build": "webpack"
},
/ /...
}
Copy the code
Then execute it on the consolenpm run dev
You can see that hot updates are implemented, but they look like F5 refreshes.We want to implement hot update, add a linehot: true
Can be
devServer: {
contentBase: './dist'.hot: true
},
Copy the code
5.2 Proxy Configuration
In the daily development process, often encounter cross-domain problems, here you can use devServer proxy configuration proxy, to achieve cross-domain requests.
webpack.config.js
module.exports = {
/ /...
devServer: {
proxy: {
'/api': 'http://localhost:3000',}}};Copy the code
If now, right/API/users request will request broker to http://localhost:3000/api/users.
If you don’t want to pass/API, you need to rewrite the path:
module.exports = {
/ /...
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000'.pathRewrite: {
'^/api': ' '},},},},};Copy the code
At that time, the will request broker/API/users request to http://localhost:3000/user
By default, backend servers running over HTTPS with invalid certificates will not be accepted. If necessary, you can modify the configuration as follows:
module.exports = {
/ /...
devServer: {
proxy: {
'/api': {
target: 'https://other-server.example.com'.secure: false,},},},};Copy the code
If you want to proxy multiple specific paths to the same target, you can use an array of one or more objects with the context attribute:
module.exports = {
/ /...
devServer: {
proxy: [{context: ['/auth'.'/api'].target: 'http://localhost:3000',},],},};Copy the code
By default, the agent retains the source of the host header, and changeOrigin can be set to True to override this behavior.
module.exports = {
/ /...
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000'.changeOrigin: true,},},},};Copy the code
See the official documentation for more tutorials
5.3 DevTool
To make it easier to track errors and warnings, JavaScript provides source maps that map compiled code back to the original source code. Devtool controls whether and how the Source map is generated. Different DevTool Settings can cause performance differences. For details, try inline-source-map and modify the configuration file. webpack.confog.js
module.exports = {
mode: 'development'.entry: './src/index.js'.// Import file
output: {
filename: '[name].[contenthash].js'.// Output file
path: path.resolve(__dirname, 'dist'),// Output file storage address
},
devtool: "inline-source-map".// Add a line here
/ /...
Copy the code
Then we type console.llog in index.js (‘ This is an error ‘) and package the project.
As a result of packaging, a map file containing the corresponding base64 content is generated and inserted into main.bundle.js
Have a trysource-map
As you can see, there is a.map file at the end of main.bundle.js that specifies the specific reference to the map file
For example, there is a scenario where we need to debug an online project and can’t add a Source map to the code, but also need to debug. You can debug it by generating a.map file and adding it to the browser, as shown below.
This allows you to debug projects deployed online locally.
Avoid inline-*** and eval-*** in production as they increase the bundle size and reduce overall performance.
We can configure devtool in production with ‘source-map’, but do not deploy the map file on it. Alternatively, you can leave the devtool option unconfigured so that the map file is not generated.
5.4 External Extension (externals)
The externals configuration option provides the method to “exclude dependencies from the output bundle”. This means that dependencies imported in a project through import are not packaged into the bundle when packaged, but are accessed through script imports.
For example, importing jQuery from CDN instead of packaging it:
index.html
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
Copy the code
webpack.config.js
module.exports = {
/ /...
externals: {
jquery: 'jQuery',}};Copy the code
This strips out the dependencies that don’t need to be changed. Let’s add Jq to index.js and see what we print:
import $ from 'jquery';
console.log($('#app'));
Copy the code
5.5 the cache
SplitChunksPlugin can be used to separate modules into separate bundles. Webpack also provides an optimization function, can use optimization. RuntimeChunk option to the runtime code into a separate chunk. Set it to Single to create a Runtime bundle for all chunks
It is recommended to extract third-party libraries (such as Lodash or React) into a separate Vendor Chunk file because they are rarely modified as frequently as native source code.
We add the code in webpack.config.js
module.exports = {
/ /...
// https://webpack.docschina.org/guides/caching/
optimization: {
moduleIds: 'deterministic'./ / using optimization runtimeChunk option to the runtime code into a separate chunk
runtimeChunk: 'single'.splitChunks: {
// Make use of the client's long-acting caching mechanism to hit the cache to eliminate requests and reduce the retrieval of resources from the server.
// It also ensures that the client code and server code versions are consistent. This can be done by
// Use SplitChunksPlugin's cacheGroups option.
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors'.chunks: 'all',},},},},}Copy the code
As you can see, the main file size is reduced from 1.78MiB to 13.2KiB
Adding optionsmoduleIds: 'deterministic'
The hash of all three files has changed. This is because each module.id is incremented by default based on the resolve order. That is, when the parse order changes, the ID changes with it. So, in a nutshell:
The Main bundle changes as its new content changes. Vendor bundle changes as its module.id changes. The Manifest Runtime changes because it now contains a reference to a new module.
The first one and the last one both conform to the expected behavior, and the change of vendor hash is what we need to fix. We set optimization.moduleids to Deterministic.
Let’s rerun the project
Now, regardless of whether or not you add any new local dependencies,vendor hash
They should all be consistent.
Vi. Production environment
6.1 configuration
In a development environment, we need: a powerful source map and a Localhost Server with live reloading or hot Module replacement capabilities.
Production environment goals move to other areas, focusing on bundle compression, lighter source maps, resource optimizations, and so on to improve load times.
Following logical separation, we generally recommend writing separate WebPack configurations for each environment.
Create a new build folder in the root directory, create a new webpack.common.js file in the build folder to place the generic configuration, and create the production mode webpack.prod.js and development mode webpack.dev.js configuration files. To merge these configurations together, we will use a tool called Webpack-Merge.
The path to __dirname has changed
npm install --save-dev webpack-merge
Copy the code
webpack.common.js
//webpack.common.js
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js'.// Import file
output: {
filename: '[name].[contenthash].js'.// Output file
path: path.resolve(__dirname, '.. /dist'),// Output file storage address
},
resolve: {
extensions: ['.vue'.'.js'].// Indicates that the file suffix can be omitted when importing files
alias: {
The '@': path.join(__dirname, '.. /src')
// Import files in SRC can be written as @/component/...}},plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'I am the title of the webpack.config configuration'.template: './public/index.html'.HTML / / compression
minify: {
removeComments: true.// Remove comments from HTML
collapseWhitespace: true // Remove whitespace and newline characters}})].module: {
rules: [{test: /\.css$/i,
use: ['style-loader'.'css-loader'],}, {test: /\.(jpe? g|png|gif|svg)$/i,
type: 'asset'.// Automatically choose between exporting a data URI and sending a separate file
},
{
test: /\.js$/,
exclude: /node_modules/,
use: ['babel-loader']]}},// https://webpack.docschina.org/guides/caching/
optimization: {
// The deterministic option is beneficial for long-term caching
moduleIds: 'deterministic'./ / using optimization runtimeChunk option to the runtime code into a separate chunk
runtimeChunk: 'single'.splitChunks: {
// Make use of the client's long-acting caching mechanism to hit the cache to eliminate requests and reduce the retrieval of resources from the server.
// It also ensures that the client code and server code versions are consistent. This can be done by
// Use SplitChunksPlugin's cacheGroups option.
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors'.chunks: 'all',},},},},};Copy the code
Webpack.dev.js development environment: debug location, hot replacement, etc
//webpack.dev.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development'.devtool: 'inline-source-map'.devServer: {
contentBase: '.. /dist'.hot: true}});Copy the code
Webpack.prod. js production environment: code compression, common module separation, resource optimization, etc
//webpack.prod.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production'.devtool: "source-map"});Copy the code
We then redirect the script in package.json to the new configuration, Make the NPM run dev script webpack-dev-server use webpack.dev.js and the NPM run build script use webpack.prod.js
package.json
/ /...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"."dev": "webpack serve --open chrome --config build/webpack.dev.js"."build": "webpack --config build/webpack.prod.js"
},
/ /...
Copy the code
6.2 Removing and Compressing the CSS
MiniCssExtractPlugin The MiniCssExtractPlugin extracts CSS into a separate file, creates a CSS file for each JS file containing CSS, and supports on-demand loading of CSS and SourceMaps.
npm install --save-dev mini-css-extract-plugin
Copy the code
The plugin extracts CSS into a separate style file and adds it to the HTML, so this conflicts with style-loader. Let’s modify the configuration file.
//webpack.common.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
/ /...
plugins: [
new MiniCssExtractniPlugin({
filename: '[name].[contenthash].css'})].module: {
rules: [{test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],},],},/ /...
};
Copy the code
The MiniCssExtractPlugin plugin is usually used in production environments, and we can continue to use style-loader in re-development environments.
So we will modify the configuration file again, using style-loader in webpack.dev.js and MiniCssExtractPlugin in webpack.prod.js
Next, compress the output CSS file and install the CSS-minimizer-webpack-plugin.
npm i -D css-minimizer-webpack-plugin
Copy the code
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
module.exports = {
/ /...
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'.chunkFilename: '[id].css',})],module: {
rules: [{test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],},],},optimization: {
minimizer: [
new CssMinimizerPlugin({
parallel: true // Use multi-process concurrent execution to improve build speed})],}};Copy the code
When we execute the package command, we can see that the CSS has been compressed.
This will only turn on CSS optimization in production.
If you also want to enable CSS optimization in your development environment, set optimization.minimize to true.
When not added, the resulting main file is 31.4kib
We add it to webpack.dev.js
//webpack.dev.js
module.exports = merge(common, {
/ /...
optimization: {
minimize: true}})Copy the code
Run it and you can see that the main file is 13.2KiB
6.3 js compressed
The TerserWebpackPlugin uses Terser to compress JavaScript.
If you are using WebPack V5 or above, you do not need to install this plugin. Webpack V5 comes with the latest Terser-webpack-plugin. If you use Webpack V4, you must install the version of Terser-webpack-Plugin V4.
For debugging convenience, the development process, do not compress the code. Let’s add it to the build environment.
// webpack.prod.js
const TerserPlugin = require("terser-webpack-plugin");
module.exports = merge(common, {
// ...
optimization: {
// https://webpack.docschina.org/plugins/terser-webpack-plugin/
Js / / compression
minimize: true
minimizer: [
// https://webpack.docschina.org/plugins/terser-webpack-plugin/
Js / / compression
new TerserPlugin({
parallel: true // Use multi-process concurrent execution to improve build speed})]}})Copy the code
Run, package our project, and see the generated JS file compressed into a single line.
6.4 Image Compression
Oh ho, see other blog all have picture compression, I also add.
Go ahead and follow the website
Plug-ins need to be installed
npm install image-minimizer-webpack-plugin --save-dev
Copy the code
There are two modes of image optimization
One is lossless mode is lossy mode all the time
The website recommends lossless plug-ins
npm install imagemin-gifsicle imagemin-jpegtran imagemin-optipng imagemin-svgo --save-dev
Copy the code
The official website recommends lossy plug-ins
npm install imagemin-gifsicle imagemin-mozjpeg imagemin-pngquant imagemin-svgo --save-dev
Copy the code
Add code to webpack.prod.js
// webpack.prod.js
/ /...
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');
module.exports = {
/ /...
plugins: [
/ /...
new ImageMinimizerPlugin({
minimizerOptions: {
// Non-destructive setting
plugins: [['gifsicle', { interlaced: true }],
['jpegtran', { progressive: true }],
['optipng', { optimizationLevel: 5 }],
[
'svgo',
{
plugins: [{removeViewBox: false,},],},],],},})]}Copy the code
Pack the project, and you can see that the images in DIST are smaller.
Note: this is based on file matching in “3.3 Loading images”. This is because such files need to be identified before they can be compressed. I missed matching jpeg files earlier. Compression errors occur. Thank me for asking the question without a coke.
7. Integrate Vue3
First, let Webpack recognize the.vue file. You need vue-loader plug-in, install plug-in.
npm install vue@next -S
npm install -D vue-loader@next @vue/compiler-sfc
Copy the code
Note: Vue2. X installs vue-template-complier
Vue-loader: parses and transforms the. Vue file, extracts the logical code script, style code style, and HTML template, and then sends them to the corresponding loader for processing.
Let’s start by configuring WebPack to recognize.vue files
//webpack.common.js
const { VueLoaderPlugin } = require('vue-loader/dist/index');
module.exports = {
/ /...
plugins: [
/ /...
new VueLoaderPlugin() // Plugin for parsing and converting.vue files].module: [
rules: [
/ /...
{
test: /\.vue$/,
use: ['vue-loader'[}]]}Copy the code
Try creating the app. vue file in the SRC directory
<! --App.vue-->
<template>
<div>Hello, X1AXX1A</div>
</template>
<script>
import { defineComponent } from "vue"
export default defineComponent({
setup() {
console.log('I'm a printer in the App')}})</script>
<style scoped>
@import '@/index.css';
</style>
Copy the code
Modify the index.js file
//index.js
import App from './App.vue'
import { createApp } from 'vue'
createApp(App).mount('#app')
Copy the code
Add div with id app to index.html
<! --index.html-->
<! DOCTYPEhtml>
<html>
<head>
<meta charset="utf-8">
<title><%= htmlWebpackPlugin.options.title %></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<div id="app"></div>
</body>
</html>
Copy the code
Next, load the Vue bucket Vuex, VUE-Router, and Axios
npm install vuex@next --save
Copy the code
Then create a store folder under the SRC directory and create index.js and modules folders under the Store folder.
The modules folder stores various store modules. We’ll add a new user module, user.js under modules
// src/store/modules
const state = () = > ({
token: null
})
const getters = {
token: (state) = > state.token
}
const mutations = {
SET_TOKEN (state, payload) {
state.token = payload
}
}
export default {
namespaced: true,
state,
getters,
mutations
}
Copy the code
Then use require.context to dynamically load files in the Modules folder.
// src/store/index.js
import { createStore } from 'vuex'
const files = require.context('./modules'.false./\.ts$/)
const modules = {}
files.keys().forEach((key) = > {
modules[key.replace(/(\.\/|\.ts)/g.' ')] = files(key).default
})
console.log('X1AXX1A modules', modules)
export default createStore({
modules
})
Copy the code
Print and look at the obtained User module
This file is then imported in the entry file
// index.js
import App from './App.vue'
import { createApp } from 'vue'
import store from './store'
createApp(App).use(store).mount('#app')
Copy the code
At this point, you can use store in your component
We print in app.vue
// App.vue
import { defineComponent } from "vue"
import { useStore } from 'vuex'
export default defineComponent({
setup() {
let store = useStore()
console.log('store', store)
console.log('I'm the print of 123112 in the App')}})Copy the code
Next, install the router
npm install vue-router@next
Copy the code
Create a router folder under SRC and index.js under the router folder. Add the following code
// src/router/index.js
import { createRouter, createWebHashHistory } from 'vue-router'
import store from '.. /store'
const routes = [
{
path: '/ 404'.name: 'NotFound'.component: () = > import('@/views/NotFound.vue')}, {path: '/'.name: 'Index'.component: () = > import(/* webpackChunkName: "about" */ '@/views/Index.vue')}, {CatchAll (.*)' /:catchAll(.*)'
// caught Error: Catch all routes ("*") must now be defined using a param with a custom regexp
path: '/:catchAll(.*)'.// Special attention should be paid to placing it at the bottom
redirect: '/ 404'}]const router = createRouter({
history: createWebHashHistory(), Hash mode: createWebHashHistory, history mode: createWebHistory
routes
})
export default router
Copy the code
Import the file in the import file
// index.js
import App from './App.vue'
import { createApp } from 'vue'
import store from './store'
import router from './router'
createApp(App).use(store).use(router).mount('#app')
Copy the code
Modify the App. Vue
// App.vue
<template>
<router-view />
</template>
<script>
import { defineComponent } from "vue"
export default defineComponent({})
</script>
Copy the code
Create a new index. vue in views and add the following code to index. vue
// SRC /views/ index.vue <template> <div> </template> <script> import {defineComponent} from "vue" // import { useStore } from 'vuex' import { useRouter, useRoute } from 'vue-router' export default defineComponent({ setup() { // let store = useStore() let router = useRouter() let route = useRoute() // console.log('store', store) console.log('router', router) console.log('route', }}) </script>Copy the code
Next up is Axios
npm i axios
Copy the code
Wrap AXIos, do request interception, and so on, as we like to do.
import axios from 'axios'
// Add request interceptor
axios.interceptors.request.use(function(config){
// Do something before sending the request
return config;
},function(error){
// Do something when the request is wrong
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use((response) = >{
// Do something with the response data
return response;
},(error) = >{
return Promise.reject(error);
});
export default axios
Copy the code
With that in mind, we’re ready to start our Vue 3 project journey.
Finally, thank you for reading this article, I hope you can help, if you have any questions welcome to point out.
Reference:
Babel7