1. Introduction
Thanks to the Parcel packaging tool, WebPack4 is also pursuing zero-configuration build projects. Vue-cli 3.0, which appeared a while ago, is also based on the idea of webpack4 zero configuration. For some used to Webpack3 developers inevitably some not used to. This article will take you around vuE-CLI, with Webpack4 step by step build vUE project.
Note: This article describes the basic configuration of Webpack4. It is a bit long, please read it patiently. Or just look at itProgram source codeOr,ctrl + w
)
2. Project construction
-
Create the createVue folder, go to that folder, and NPM init initializes the project
-
Install the WebPack
npm i webpack webpack-cli webpack-dev-server webpack-merge --save-dev
// I am currently using the version
"webpack": "^ 4.16.3"."webpack-cli": "^ 3.1.0"."webpack-dev-server": "^ 3.1.5." ".// Development server
"webpack-merge": "^ 4.1.4." " // WebPack configuration merge
Copy the code
- Create corresponding files
createVue
|--dist
|--build
|--webpack.prod.js
|--webpack.dev.js
|--webpack.base.js
|--src
|--index.js
|--app.vue
|--index.html
Copy the code
// webpack.base.js
// Store dev and prod general configuration
const webpack = require('webpack');
const path = require("path");
module.exports = {
entry: './src/index.js'./ / the entry
module: {
rules: []},plugins: [
// Resolve that the hash behind vender changes every time
new webpack.HashedModuleIdsPlugin(),
],/ / the plugin
};
Copy the code
// webpack.dev.js
// Save the dev configuration
const merge = require('webpack-merge');
const common = require('./webpack.base.js');
const path = require('path');
module.exports = merge(common, {
devtool: 'inline-source-map'.devServer: { // Development server
contentBase: '.. /dist'
},
output: { / / output
filename: 'js/[name].[hash].js'.// The hash changes every time you save it
path: path.resolve(__dirname, '.. /dist')},module: {},
mode: 'development'});Copy the code
// webpack.prod.js
// Store the proD configuration
const path = require('path');
// Merge configuration files
const merge = require('webpack-merge');
const common = require('./webpack.base.js');
module.exports = merge(common, {
module: {},
plugins: [].mode: 'production'.output: {
filename: 'js/[name].[contenthash].js'.// Contenthash If the file content does not change, the contenthash name does not change
path: path.resolve(__dirname, '.. /dist')}});Copy the code
Webpack4 adds the mode property, which is set to Development/Production. This is the default configuration
Development: process.env.node_env set to development the following plug-ins are enabled by default to make full use of persistent caching. NamedChunksPlugin: Solidify chunk ID by name NamedModulesPlugin: Solidify Module ID production by name: Setting the value of process.env.node_env to production enables the following plug-ins by default, Including SideEffectsFlagPlugin and UglifyJsPlugin for tree - shaking FlagDependencyUsagePlugin: compile time depends on tag FlagIncludedChunksPlugin: Markup chunks, prevent child chunks loaded ModuleConcatenationPlugin: NoEmitOnErrorsPlugin: Scope hosting (scope hosting) : Scope hosting (scope hosting) : Scope hosting (scope hosting) During the output phase, a compilation error is encountered skipping OccurrenceOrderPlugin: give the shorter value SideEffectsFlagPlugin to the frequently used IDS: Recognize the sideEffects flag of package.json or module.rules (pure ES2015 modules) and safely remove unused onesexportExport UglifyJsPlugin: Remove unreferenced code and compress itCopy the code
// index.js
NPM I vue --save
import Vue from 'vue';
import App from './App.vue'
import './index.scss'
new Vue({
el: '#app'.render: h= > h(App),
});
Copy the code
<! -- app.vue -->
<template>
<div id="app">
hello world
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style scoped>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
transform: rotate(0deg);
}
</style>
Copy the code
<! -- index.html -->
<html>
<head>
<meta charset="UTF-8">
<title>Suporka Vue App</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
Copy the code
- Install the VUE core parsing plug-in
npm i vue-loader vue-template-compiler --save-dev
// I am currently using the version
"vue-loader": "^ 15.2.6"."vue-template-compiler": "^ 2.5.17".Copy the code
Because the parsing of vue is used in both DEV and PROd, it falls under base configuration
// webpack.base.js
/ /... ellipsis
/ / the vue - loader plug-in
const VueLoaderPlugin = require('vue-loader/lib/plugin');
module.exports = {
/ /... ellipsis
module: {
rules: [{test: /\.vue$/.loader: 'vue-loader'}},plugins: [
// Be sure to introduce this plugin to cast magic
new VueLoaderPlugin(),
]
};
Copy the code
- Install the HTML template parsing plug-in
npm i html-webpack-plugin --save-dev
// Current version
"html-webpack-plugin": "^ 3.2.0"
Copy the code
HTML parsing is also a basic configuration, under Base
// webpack.base.js
/ /... ellipsis
/ / HTML plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
/ /... ellipsis
plugins: [
/ /... ellipsis
new HtmlWebpackPlugin({
template: path.resolve(__dirname, '.. /index.html'),})]};Copy the code
- Create the NPM command
"scripts": {
"start": "webpack-dev-server --hot --open --config build/webpack.dev.js",
"build": "webpack --config build/webpack.prod.js"
},
Copy the code
— Hot Module hot replacement
–open Enables the local server
At this point NPM start, the project can run normally
3. Function expansion
- Add the loader
- CSS Loader (including pre and post processing)
CSS based loader
"css-loader": "^ 1.0.0"."style-loader": "^ 0.21.0".Copy the code
The CSS processes less
"less": "^ 3.8.0." "."less-loader": "^ 4.1.0." ".Copy the code
The CSS has two sets of sass
"node-sass": "^ 4.9.2." "."sass-loader": "^ 7.1.0".Copy the code
CSS postprocessing PostCSS consists of two modules
"postcss-loader": "^ 2.1.6"."autoprefixer": "^ 9.1.0".Copy the code
Create the postcss.config.js file in the root folder
// postcss.config.js
// Automatically add CSS compatibility properties
module.exports = {
plugins: [
require('autoprefixer')]}Copy the code
To install the above dependencies, add the following loader code to the base file
// webpack.base.js
/ /... ellipsis
rules: [
{
test: /\.(sa|sc|c)ss$/.use: [
'style-loader'.'css-loader'.'postcss-loader'.'sass-loader',]}, {test: /\.less$/.use: [
'style-loader'.'css-loader'.'postcss-loader'.'less-loader',]}]Copy the code
- Image loader
Install NPM I file-loader –save-dev
Add the base file to the configuration
// webpack.base.js
/ /... ellipsis
rules: [
/ /... ellipsis
{
test: /\.(png|svg|jpg|gif)$/.use: [{loader: 'file-loader'.options: {
limit: 5000.// Separate images to imGS folder
name: "imgs/[name].[ext]",}},]},]Copy the code
4. Package optimization
- Dist folder files are not cleared each time you repack
- Install the clean-Webpack-plugin
// webpack.prod.js
// Clear files before packing
const CleanWebpackPlugin = require('clean-webpack-plugin');
/ /... ellipsis
plugins: [
new CleanWebpackPlugin(['dist/*'] and {root: path.resolve(__dirname, '.. / ')}),]Copy the code
- The separation of CSS
Webpackage 4 uses the mini-CSs-extract-plugin to separate CSS.
- After installing the mini-CSS-extract-plugin plugin
// webpack.prod.js
// Separate CSS plugins
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
/ /... ellipsis
plugins: [
new MiniCssExtractPlugin({
filename: "css/[name].[hash].css".chunkFilename: 'css/[id].[hash].css'}),]Copy the code
In addition, replace style-loader in each CSS loader with MiniCssExtractPlugin
Image compression using image-webpack-loader, after installation code is as follows:
// webpack.prod.js
/ /... ellipsis
rules: [
{
test: /\.(sa|sc|c)ss$/.use: [{loader: MiniCssExtractPlugin.loader,
options: {
// you can specify a publicPath here
// by default it use publicPath in webpackOptions.output
publicPath: '.. / '}},'css-loader'.'postcss-loader'.'sass-loader',]}, {test: /\.less$/.use: [{loader: MiniCssExtractPlugin.loader,
options: {
// you can specify a publicPath here
// by default it use publicPath in webpackOptions.output
publicPath: '.. / '}},'css-loader'.'postcss-loader'.'less-loader',]}, {test: /\.(png|svg|jpg|gif)$/.use: [{loader: 'file-loader'.options: {
limit: 5000.name: "imgs/[hash].[ext]",}},// Image compression
{
loader: 'image-webpack-loader'.options: {
// bypassOnDebug: true,
mozjpeg: {
progressive: true.quality: 65
},
optipng: {
enabled: false,},pngquant: {
quality: '65-90'.speed: 4
},
gifsicle: {
interlaced: false,}},},]},]Copy the code
- Use Happypack multiple processes to speed up compilation
You also need to install the Babel two-piece set
"babel-core": "^ 6.26.3"."babel-loader": "^ 7.1.5." "."happypack": "^ 5.0.0".Copy the code
Happypack development production environment is used, configuration into base
// webpack.base.js
/ / use happypack
const HappyPack = require('happypack');
const os = require('os');
const happyThreadPool = HappyPack.ThreadPool({ size: os.cpus().length });
/ /... ellipsis
rules: [
{
test: /\.js$/.// pass the.js file processing to the HappyPack instance with id happyBabel
loader: 'happypack/loader? id=happyBabel'.// Exclude files in node_modules
exclude: /node_modules/
},
]
plugins: [
/ /...
new HappyPack({
// Use id to identify the happypack processing class file
id: "happyBabel".// How to handle the same usage as the loader configuration
loaders: [
{
loader: "babel-loader? cacheDirectory=true"}].// Share the process pool
threadPool: happyThreadPool,
// Allow HappyPack to output logs
verbose: true}),]Copy the code
- Separate infrequently changing files, such as libraries referenced under node_modules
// webpack.prod.js
module.exports = merge(common, {
/ /... ellipsis
optimization: {
/ / separate chunks
splitChunks: {
chunks: 'all'.cacheGroups: {
vendor: {
name: "vendor".test: /[\\/]node_modules[\\/]/.priority: 10.chunks: "initial" // Package only the third party that you originally relied on},}},},})Copy the code
If configured this way, there will be an extra vendor.js in the packaged JS folder
- Compress CSS and JS code
Install the optimize- CSS -assets-webpack-plugin and uglifyjs-webpack-plugin plugins
// webpack.prod.js
// Compress CSS and JS code
/ /... ellipsis
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports = merge(common, {
/ /... ellipsis
optimization: {
/ /... ellipsis
minimizer: [
JS / / compression
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false.// Remove the warning
drop_debugger: true./ / remove the debugger
drop_console: true / / remove the console log}},cache: true.// Enable caching
parallel: true.// Parallel compression
sourceMap: false // set to true if you want JS source maps
}),
/ / compress CSS
new OptimizeCSSAssetsPlugin({})
]
},
})
Copy the code
Finally, extend the distinction between hash, chunkhash, and contenthash
-
Hash is related to the construction of the entire project. Whenever a file changes in the project, the hash value of the entire project will change and all files will share the same hash value
-
Chunkhash is different from hash. It parses dependent files based on different Entry files, constructs corresponding chunks, and generates corresponding hash values.
-
Contenthash changes the content in more detail, generating the corresponding hash value. Resolve a problem where the file name introduced in the chunkhash file changes due to chunkhash changes
Program source code