In 2022, will not use Webpack to build projects how much can not be said, based on the latest Webpack 5.65 build, hand to hand teach you to build VUE projects, subsequent optimization integration and other dependencies will continue to update.
Create a project
- Specify a directory to open a command line window and run the following commands in sequence:
- mkdir webpack-vue
- cd webpack-vue
- NPM init // Initializes package.json
Initialize the webpack
- npm install webpack webpack-cli -D
- Modify package.json to add startup command
// package.json{..."scripts": {
"test": "echo "Error: no test specified" && exit 1"."dev": "webpack --mode development"."build": "webpack --mode production"}},Copy the code
Entrance to the file
-
Create a new SRC folder in the root directory (mimicking vue)
-
Create main.js in SRC
-
New webpack.config.js (configuration file)
// The current webpack.config.js configuration
const path = require('path');
module.exports = {
entry: './src/main.js'./ / the entry
output: { / / output
filename: 'main.js'.path: path.resolve(__dirname, 'dist')}};Copy the code
-
NPM run build (root dist: main.js)
-
Create the index.html template in the root directory
-
NPM install html-webpack-plugin -d (install HTML plugin, change webpack.config.js configuration)
// The current webpack.config.js configuration
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/main.js'./ / the entry
output: { / / output
filename: 'main.js'.path: path.resolve(__dirname, 'dist')},plugins: [
new HtmlWebpackPlugin({
template: './index.html',}})]Copy the code
- Create an assets/ CSS folder in the SRC directory and an index. CSS folder
html.body{
height: 100%;
width: 100%;
margin: 0;
padding: 0;
background: red;
}
Copy the code
- npm install css-loader style-loader -D
- Webpack.config. js Adds loader configuration
// ...
module: {
rules: [{
test: /.css$/,
use: [
'style-loader'.'css-loader']]}},Copy the code
- The main. Js, the introduction of the index. The CSS
import ('./assets/css/index.css')
- NPM run build dist Directory in index. HTML using live Server If the background is in red, loader takes effect
Integrated hot update
- npm install webpack-dev-server -D
- Modify the webpack.config.js configuration
/ / webpack. Config. Js added
devServer: {
static: path.join(__dirname, 'dist'), // The root directory of the server resource
hot: true.// Enable hot loading
host: 'localhost'.port: 9000./ / the port number
open: true.// Open the default browser after the server starts
},
Copy the code
- Modify the index. CSS file background:blue. If the page background changes to blue, the hot update takes effect
See more devServer configurations here
Integrated Vue3
- NPM install vue@next // Install the latest vue3
- NPM i-d vue-loader@next @vue/ compiler-sFC // Let WebPack support VUE syntax and single-file components (SFC)
// Current configuration version
"scripts": {
"test": "echo "Error: no test specified" && exit 1"."dev": "webpack serve --mode development"."build": "webpack --mode production"
},
"author": ""."license": "ISC"."devDependencies": {
"@vue/compiler-sfc": "^ 3.2.26"."css-loader": "^ 6.5.1." "."html-webpack-plugin": "^ 5.5.0"."style-loader": "^ 3.3.1"."vue-loader": "^ 17.0.0"."webpack": "^ 5.65.0"."webpack-cli": "^ 4.9.1." "."webpack-dev-server": "^ 4.7.3." "
},
"dependencies": {
"vue": "^ 3.2.26"
}
Copy the code
- Create app.vue in the SRC directory
- Modify the webpack.config.js configuration
// The current configuration is complete
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader'); / / introduce VueLoaderPlugin
module.exports = {
/ / the entry
entry: './src/main.js'./ / export
output: {
filename: 'main.js'.path: path.resolve(__dirname, 'dist')},module: {
rules: [{test: /.css$/,
use: [
'style-loader'.'css-loader']},/ / configuration vue - loader
{
test: /.vue$/,
use: ['vue-loader']]}},plugins: [
new HtmlWebpackPlugin({
template: './index.html'
}),
new VueLoaderPlugin() / / new VueLoaderPlugin].devServer: {
static: path.join(__dirname, 'dist'), // The root directory of the server resource. The default directory is bundle.js
hot: true.// Enable hot loading
host: 'localhost'.port: 9000./ / the port number
open: true.// Open the default browser after the server starts}},Copy the code
- Modify the index.html file
<body>
<div id="app"></div>
</body>
- Modify the main.js configuration
// The current main.js configuration
import ('./assets/css/index.css');
import {createApp} from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
Copy the code
- NPM run dev can see that the vue file has compiled properly
Integrated SCSS
- The following uses SASS as an example
npm install node-sass sass-loader -D
It’s easy to fail. Try two more times
- Modify webpack.config.js loader configuration
// ...
{
test: /.(s[ac]ss|css)$/i.// Matches sASS and CSS
use: [
'style-loader'.'css-loader'.'sass-loader']},Copy the code
- App.vue file changes the style style
<style lang="scss">
#app{
color: green;
}
</style>
Copy the code
- If the NPM run dev style takes effect, sASS is successfully integrated
Integrated vue – the router
- NPM install vue-router@4 // Note that @4 is important to declare the installed version
- Create the views folder under the SRC directory, and create three Vue files A, B and C under the folder
// A.vue
<template>
<div>
<h1> this is page A </h1>
<a @click="$router.push('B')">Page B</a>
<br/>
<a @click="$router.push('C')">Page C</a>
<! -- Subroute -->
<router-view></router-view>
</div>
</template>
// ...
// B.vue / C.vue
<template>
<div>
this is page B / C
</div>
</template>
Copy the code
- Create the route/index.js file in the SRC directory
import { createRouter,createWebHistory } from "vue-router";
const router = createRouter ({
history:createWebHistory(), / / the history model
routes: [{path: '/'.redirect: { name: 'A'}, {},name: 'A'.path: '/A'.component: () = > import('.. /views/A.vue'),
children: [{name: 'C'.path: '/C'.component: () = > import('.. /views/C.vue'}]}, {name: 'B'.path: '/B'.component: () = > import('.. /views/B.vue')}]})export default router;
Copy the code
- Main.js imports routes
import ('./assets/css/index.css');
import {createApp} from 'vue'
import App from './App.vue'
import router from './route'
createApp(App).use(router).mount('#app')
Copy the code
- App.vue adds components
- NPM run dev starts the project and you can see that routing is working properly and page A nested routines are working properly
- Updated the problem of route 404 and modified the Webpack configuration
// webpack.config.js
// ...
devServer: {
static: path.join(__dirname, 'dist'), // The root directory of the server resource. The default directory is bundle.js
hot: true.// Enable hot loading
host: 'localhost'.port: 9000./ / the port number
open: true.// Open the default browser after the server starts
historyApiFallback: true.// Resolve the history mode refresh 404
},
Copy the code
Integrated vuex
- npm install -save vuex@4.*
- Create store/index.js in the SRC directory
- The main. Js into the store
// Current configuration
import ('./assets/css/index.css');
import {createApp} from 'vue'
import App from './App.vue'
import router from './route'
import store from './store'
createApp(App)
.use(router)
.use(store)
.mount('#app')
Copy the code
- Edit store/index. Js
// make an example of the official website
import { createStore } from 'vuex'
export default createStore({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {},modules: {}})Copy the code
- The editor Dr. Ue
<template>
<div>
<h1>this is page A {{count}}</h1>
<a @click="$router.push('B')">Page B</a>
<br />
<a @click="$router.push('C')">Page C</a>
<br />
<button @click="$store.commit('increment')">increase</button>
<! -- Subroute -->
<router-view></router-view>
</div>
</template>
<script>
export default {
computed: {
count() {
return this.$store.state.count
}
},
}
</script>// verify that the vuex data is the same // c. vue<template>
<div>
this is page C {{count}}
</div>
</template>
<script>
export default {
computed: {
count() {
return this.$store.state.count
}
},
}
</script>
Copy the code
- Run Dev Sees that store data sharing takes effect
Integration of Babel
- NPM I -d babel-loader @babel/ core@babel /cli @babel/preset-env // Preset
- npm install –save core-js@3
What is core-JS?
Core-js is a polyfill of the JavaScript standard library, translating the new functionality of es’ API ‘into a collection of’ API ‘patches that most modern browsers can support and run
By contrast
Polyfill pollutes the global environment and supports instance methods
Runtime does not pollute the global environment and does not support instance methods
- The root directory is newly created. Babelrc
{
"presets": [["@babel/preset-env", {
"useBuiltIns": "usage"."corejs": 3}}]]Copy the code
- Webpack. Config. Js
module: {
rules: [
// ...
{
test: /.js$/,
use: 'babel-loader'.exclude: /node_modules/}},Copy the code
- Main.js adds some NEW ES6 + syntax
// ...
console.log(
[1.2.3].map(n= > n ** 2));() = >{console.log(123)}
Copy the code
- NPM run dev sees the ES6 + code compiled
// After compiling
console.log([1.2.3].map(function (n) {
return Math.pow(n, 2);
}));
(function () {
console.log(123);
});
Copy the code
- The package.json version information is as follows
{
"name": "webpack-vue"."version": "1.0.0"."description": ""."main": "index.js"."scripts": {
"test": "echo "Error: no test specified" && exit 1"."dev": "webpack serve --mode development"."build": "webpack --mode production"
},
"author": ""."license": "ISC"."devDependencies": {
"@babel/cli": "^ 7.16.8"."@babel/core": "^ 7.16.7"."@babel/preset-env": "^ 7.16.8"."@vue/compiler-sfc": "^ 3.2.26"."babel-loader": "^ 8.2.3"."css-loader": "^ 6.5.1." "."html-webpack-plugin": "^ 5.5.0"."node-sass": "^" 7.0.1."sass-loader": "^ 12.4.0"."style-loader": "^ 3.3.1"."vue-loader": "^ 17.0.0"."webpack": "^ 5.65.0"."webpack-cli": "^ 4.9.1." "."webpack-dev-server": "^ 4.7.3." "
},
"dependencies": {
"core-js": "^ 3.20.2"."vue": "^ 3.2.26"."vue-router": "^ 4.0.12"."vuex": "^ 4.0.2." "}}Copy the code
The separation of CSS
If you run the NPM run build command, you will find that the CSS is packaged into chunks. In a production environment, you need to separate the CSS.
- npm install -D mini-css-extract-plugin
> extract-text-webpack-plugin (mini-CSS-extract -plugin)
- Edit webpack. Config. Js
// ...
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
// loader
// ...
{
test: /.(s[ac]ss|css)$/i,
use: [
// 'style-loader',
MiniCssExtractPlugin.loader,
'css-loader'.'sass-loader']},// plugins
// ...
new MiniCssExtractPlugin({
filename: "css/[name].css".chunkFilename: "css/[name].css"
})
Copy the code
- NPM run Dev can see that the CSS reference of the page has changed from a style tag to a CSS file
So far, process.env.NODE_ENV is undefined. We need to modify the package.json directive, add NODE_ENV to the execution environment, and install cross-env, which is a script that sets up and uses environment variables across platforms. Used to distinguish node environment variables (development or production)
- npm install cross-env -D
- Modify the package.json scripts command
// ...
"scripts": {
"test": "echo "Error: no test specified" && exit 1"."dev": "cross-env NODE_ENV=development webpack serve"."build": "cross-env NODE_ENV=production webpack "
},
Copy the code
- NPM run build If the CSS file is removed, it indicates success
The difference between development and production environments
Production environments may need to separate CSS into separate files so that multiple pages share the same CSS file.
Production environments require compressed HTML/CSS/JS code;
Production environments require compressed images;
The development environment needs to generate the SourceMap file;
Debug information needs to be printed in the development environment.
The development environment requires HMR, devServer, etc…
Divide the Webpack configuration file by environment
Webpack.config. js: default entry configuration file for all environments;
Webpack.base.js: basic configuration;
Webpack.development.js: configuration used by the development environment;
Webpack.production.js: configuration for use in production environments.
Webpack configuration split
With the environmental differences described above, let’s split the existing webpack.config.js file
- Create a build folder in the root directory
- Create webpack.base.js, webpack.dev.js, and webpack.prod.js in the build folder
- Split files according to the above description of environmental differences
- NPM I webpack-merge -d // Merge configuration files feel similar to object.assign
// webpack.base.js
const { VueLoaderPlugin } = require('vue-loader');
const devConfig = require('./webpack.dev');
const prodConfig = require('./webpack.prod');
const {merge} = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const isProduct = process.env.NODE_ENV === 'production';
const baseConfig = {
/ / the entry
entry: '/src/main.js'.module: {
rules: [{test: /.(s[ac]ss|css)$/i,
use: [
isProduct ? MiniCssExtractPlugin.loader : 'style-loader'.'css-loader'.'sass-loader'] {},test: /.vue$/,
use: ['vue-loader'] {},test: /.js$/,
use: 'babel-loader'.exclude: /node_modules/}},plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: 'index.html'})],}module.exports = isProduct ? merge(baseConfig, prodConfig) : merge(baseConfig, devConfig);
Copy the code
// webpack.dev.js
const path = require('path');
module.exports = {
devServer: {
static: path.join(__dirname, 'dist'), // The root directory of the server resource. The default directory is bundle.js
hot: true.// Enable hot loading
host: 'localhost'.port: 9000./ / the port number
open: true.// Open the default browser after the server starts
historyApiFallback: true.// Resolve the history mode refresh 404}},Copy the code
// webpack.prod.js
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
/ / export
output: {
filename: 'js/[name]-[chunkhash].js'.path: path.resolve(__dirname, '.. /dist')},plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].css".chunkFilename: "css/[name].css"}})]Copy the code
- Modify the package.json command
"dev": "cross-env NODE_ENV=development webpack serve --config build/webpack.base.js"."build": "cross-env NODE_ENV=production webpack --config build/webpack.base.js"
Copy the code
- The NPM run dev/NPM run build command is successfully split
Clean up the package
Each build does not clear the files of the previous build by default
- npm install –save-dev clean-webpack-plugin
- Webpack. Prod. Edited by js
// ...
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// plugins
plugins: [
// ...
new CleanWebpackPlugin()
]
Copy the code
Processing images
Attention!! Webpack5 has deprecated url-loader/file-loader, which uses the built-in asset module to process resource files. Webpack5 already supports resource modules, which can be configured using the type parameter. Asset /resource2 asset/inline 3 Asset /source
- Create the image/cat. JPG file in the assets directory
- Dr. Ue file
// ...
<img src=".. /assets/image/cat.jpg" alt="">
<style lang="scss" scoped>
.pageA{
background: url(".. /assets/image/cat.jpg") no-repeat;
h1{
background: url('~@/assets/image/cat.jpg') no-repeat;
}
img{
width: 200px; }}</style>
Copy the code
- webpack.base.js
// loader
[
// ...
{
test:/.(jpg|png|gif)$/,
type:"asset"./ / parsing
parser: {
// Transfer base64 condition
dataUrlCondition: {
maxSize: 10 * 1024.// Files smaller than 10KB are converted to base64 addresses to reduce requests}},generator: {/ / and the output. AssetModuleFilename is the same, the time of this writing is introduced into will also add the path
filename:'img/[name]-[hash:6].[ext]'.// After the package is introduced, the file name has /img
// publicPath:'./'}}]Copy the code
- Image loading successful
CSS compatibility with Browser
- npm i postcss-loader postcss-preset-env -D
Postcss is a platform on which we can use plug-ins such as Autofix
- Webpack. Base. Edited by js
// ...
{
test: /.(s[ac]ss|css)$/i,
use: [
isProduct ? MiniCssExtractPlugin.loader : 'style-loader'.'css-loader'.'postcss-loader'.'sass-loader',]},Copy the code
- Create postcss.config.js in the root directory
module.exports = {
plugins: [[// The postCSs-preset -env plugin reads browserslist configuration in package.json file
// Create a new.browserslistrc file in the root directory
require('postcss-preset-env') (the)],]};Copy the code
- Package. Json editor
"browserslist": [
"0.05%" >."last 2 versions"."not ie <= 8"."Android 4.0" >
]
Copy the code
- Dr. Ue editor
<style lang="scss" scoped>
.pageA{
background: url(".. /assets/image/cat.jpg") no-repeat;
h1{
// background: url('~@/assets/image/cat.jpg') no-repeat;
background-color: red;
display: flex;
color: rgba(255.165.0.0.5);
justify-content: space-between;
box-sizing : border-box;
box-shadow: none;
}
img{
width: 200px; }}</style>
Copy the code
- The NPM run dev run element style has a browser prefix indicating success
// There is a delete line in the browserbackground-color: red;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
color: rgba(255.165.0.0.5);
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-box-sizing: border-box;
box-sizing: border-box;
-webkit-box-shadow: none;
box-shadow: none;
Copy the code
Configuration sourceMap
SourceMap is the source code and compiled code of the mapping relationship between an object file, our development environment and production environment to run code are compiled code, compiled code information and source code are not the same, in the development environment we need to locate the source code to the wrong position, and we need to hide this mapping file in a production environment.
- Edit webpack. Base. Js
// ...
const baseConfig = {
/ / the entry
entry: '/src/main.js'.// Hide the mapping in production or enable it in false development
devtool: isProduct ? false : 'source-map'./ /...
}
Copy the code
- Edit A. ue to print an undefined variable
- NPM run dev sees an error mapping to the source file
- SourceMap has multiple configurable items to set according to its own situation
false | eval | [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
Log beautification
In the current configuration, we have a lot of output when we run, which is pretty ugly
- NPM I friendly-errors-webpack-plugin -d // More configurations
- Edit the webpack.base.js configuration with stats to optimize the output log
const baseConfig = {
/ / the entry
entry: '/src/main.js'.devtool: isProduct ? 'hidden-source-map' : 'source-map'.stats: "errors-only".Stats is output only in error cases
// ...
plugins: [
new VueLoaderPlugin(),
new HtmlWebpackPlugin({
template: 'index.html'
}),
new FriendlyErrorsWebpackPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://localhost:9000`]}}),],}Copy the code
- NPM run dev console prints Your application is running here: http://localhost:9000 and scroll up the console to see the output log is succesfully successful
Packing progress bar
Based on the current configuration, there is no progress display when we package, so WE don’t know how anxious we are when the packaging progresses
- npm i -D progress-bar-webpack-plugin
- Edit webpack. Base. Js
// ...
const chalk = require("chalk");
const ProgressBarPlugin = require("progress-bar-webpack-plugin");
// ...
plugins: {
/ / the progress bar
new ProgressBarPlugin({
format: ` :msg [:bar] ${chalk.green.bold(":percent")} (:elapsed s)`,}})Copy the code
The alias configuration
Configuring aliases speeds up WebPack’s search for modules
// webpack.base.js
// ...
resolve: {
alias: {
The '@': path.resolve(__dirname,'.. /src') SRC is the outer layer of the current file since we are in the build directory}},Copy the code
File search range
You can specify extensions without requiring or importing extensions
The search will try in turn to add the extension name to match
// webpack.base.js
// ...
resolve: {
extensions: ['.js'.'.jsx'.'.json'].// When importing files, the default js and JSON file name extension is not used, but when importing files such as JSX file name extension cannot be used by default. If you do not want to write extension name, configure it here
alias: {
The '@': path.resolve(__dirname,'.. /src') SRC is the outer layer of the current file since we are in the build directory}},Copy the code
Babel – loader cache
The purpose of using babel-Loader in Webpack is to translate more advanced syntax into browser-aware syntax for compatibility with our JS code. The loader needs to compile, convert, and build, so it’s slow. After setting cacheDirectory, the webpack build will try to read the cache (node_modules/.cache/babel-loader). To avoid the potentially high-performance Babel recompilation process that can occur each time you execute, thereby increasing build speed.
- Edit webpack. Base. Js
// ...
{
test: /.js$/,
use :['babel-loader? cacheDirectory=true'].// Enable the Babel cache. On the second build, the previous cache will be read
exclude: /node_modules/
},
Copy the code
- NPM run build: node_modules
- Each subsequent build takes a little less time than the first build
File cache (persistent cache)
Cache: Filesystem can cache webpack templates during the build process, greatly improving the secondary build speed and packaging speed. When the build is interrupted suddenly, it can be directly pulled from the cache, increasing the speed by about 90%.
// webpack.base.js
// ...
cache: {
type: "filesystem".// Use file caching
},
Copy the code
multithreading
If you place this loader before other loaders, loaders placed after this loader will run in a separate worker pool
- npm install –save-dev thread-loader
- Edit webpack. Base. Js
{
test: /.js$/,
use: [
{
loader: "thread-loader".// Loaders with the same configuration share a worker pool (worker pool)
options: {
// The number of workers generated, by default, is the number of CPU cores
workers: 2.// The number of concurrent tasks in a worker process
// The default is 20
workerParallelJobs: 50.// Additional Node.js parameters
workerNodeArgs: ['--max-old-space-size'.'1024'].// Delete worker processes when idle
// the default is 500ms
// It can be set to infinity to keep the worker alive in watch mode (--watch)
poolTimeout: 2000.// The number of jobs assigned to the worker by the pool
// The default is 200
// Lowering this number will reduce overall efficiency, but will improve work distribution more evenly
poolParallelJobs: 50.// Pool name
// You can change the name to create a pool with the same other options.
name: "my-pool"}},'babel-loader',].exclude: /node_modules/
},
Copy the code
- Each worker is a separate Node.js process with a 600ms limit. Data exchange across processes is also limited.
- Use this command only on time-consuming Loaders
Happypack is also used to set up multithreading, but it is no longer used in Webpack5.
conclusion
This article is their own recently built project step by step recorded, because it is empty project, so optimization do not do much, interested in Webpack, but did not build a Webpack project friends can try to build a Webpack project from zero, I believe that this process will let you have a good harvest.
// The current dependency information package.json
{
"name": "webpack-vue"."version": "1.0.0"."description": ""."main": "index.js"."scripts": {
"test": "echo \"Error: no test specified\" && exit 1"."dev": "cross-env NODE_ENV=development webpack serve"."build": "cross-env NODE_ENV=production webpack "."start": "cross-env NODE_ENV=development webpack serve --config build/webpack.base.js"."done": "cross-env NODE_ENV=production webpack --config build/webpack.base.js"
},
"author": ""."license": "ISC"."devDependencies": {
"@babel/cli": "^ 7.16.8"."@babel/core": "^ 7.16.7"."@babel/preset-env": "^ 7.16.8"."@vue/compiler-sfc": "^ 3.2.26"."babel-loader": "^ 8.2.3"."clean-webpack-plugin": "^ 4.0.0"."cross-env": "^ 7.0.3." "."css-loader": "^ 6.5.1." "."friendly-errors-webpack-plugin": "^ 1.7.0"."html-webpack-plugin": "^ 5.5.0"."mini-css-extract-plugin": "^ 2.4.6." "."node-sass": "^" 7.0.1."postcss-loader": "^ 6.2.1." "."postcss-preset-env": "^ 7.2.3." "."progress-bar-webpack-plugin": "^ 2.1.0." "."sass-loader": "^ 12.4.0"."style-loader": "^ 3.3.1"."thread-loader": "^ 3.0.4"."vue-loader": "^ 17.0.0"."webpack": "^ 5.65.0"."webpack-cli": "^ 4.9.1." "."webpack-dev-server": "^ 4.7.3." "."webpack-merge": "^ 5.8.0"
},
"dependencies": {
"core-js": "^ 3.20.2"."vue": "^ 3.2.26"."vue-router": "^ 4.0.12"."vuex": "^ 4.0.2." "
},
"browserslist": [
"0.05%" >."last 2 versions"."not ie <= 8"."Android 4.0" >]}Copy the code