Some basic knowledge points of webpack
Core concept
- Entry: an entry that performs the first step of the build
- Module: it will recursively find out all dependent modules from the configured Entry
- Chunk: used for code splitting and merging
- Loader: module converter
- Plugin: an extension that injects extension logic at a specific time to change the build result
- Output: output results
webpack is a tool for packaging jacascript. It can't recognize other files, so it needs to configure loader for recognition
Foreword project directory structure
├─build │ ├─webpack.base.conf.js //Operational profiles are available in both development and production environments │ ├─webpack.dev.conf.js //Development environment profile │ ├─webpack.prod.conf.js //Production environment profile │ ├─webpack.rules.conf.js //Module matching rules ├─node_modules //Dependent file ├─public //Static file storage location | |-index.html //Project template file └─src | ├─plugins | ├─router | ├─store | ├─views | |-App.vue | |-main.ts | |-shims-vue.d.ts |-.env.dev //Environmental documents |-.env.test |-.env.prod |-.gitigore |-babel.config.js //bable profile |-package.json |-postcss.config.js //Adaptation rules |-tsconfig.json
1. Step 1: initialize the project
yarn init -y Initialize project //-y yes yes yes one click initialization
2. Step 2: install the webpack three piece set
// Installing the webpack Three Piece Kit yarn add webpack webpack-cli webpack-dev-server -D // -D is equivalent to the dependency of -- save dev development environment // -S is equivalent to the dependency of -- save production environment //use http://localhost:8080/webpack -Dev server / can access the files generated in memory by the webpack dev server command
3. Create configuration files by function
├─build │ ├─webpack.base.conf.js //Public configuration │ ├─webpack.dev.conf.js //mode is configured for development │ ├─webpack.prod.conf.js //mode is configured for production │ ├─webpack.rules.conf.js //loader configuration
3.1 create src folder and create main.js file in it
3.2 writing entry path and output path
//webpack.base.conf.js const path = require("path") module.exports = function (proMode) { return { // JavaScript execution entry file entry: path.resolve(__dirname, "../src/main.ts"), output: { // The output files are placed in the dist directory path: path.resolve(__dirname, "../dist"), // Merge all dependent modules and output them to a bundle.js file filename: "./js/[name].[chunkhash].js", // publicPath: ". /", / / used in production environment clean: true }, } }
4 create environment files
.env.dev .env.test .env.prod
4.1 content of writing environment
//.env.dev NODE_ENV="development" VUE_APP_BASE_API="/api" VUE_APP_API_USER="/user" VUE_APP_SHOWCONSOLE=true
4.2 configuring environment variables
//Dotenv is a zero dependency module that loads variables in environment variables from the. env file into process.env // Installing dotenv yarn add dotenv -D yarn add cross-env -D //webpack.base.conf.js const webpack = require("webpack") const envMode = process.env.envMode require("dotenv").config({ path: `.env.${envMode}` }) const prefixRE = /^VUE_APP_/ let env = {} for (const key in process.env) { if (key == "NODE_ENV" || key == "BASE_URL" || prefixRE.test(key)) { env[key] = JSON.stringify(process.env[key]) } } module.exports = function (proMode) { return { plugins: [ new webpack.DefinePlugin({ // Define environment and variables 'process.env': { ...env } }), ], } }
4.3 modify package.json startup command
"scripts": { "dev": "cross-env envMode=dev webpack serve --config ./build/webpack.dev.conf.js --color", "build": "cross-env envMode=prod webpack --config build/webpack.prod.conf.js --color", "build:test": "cross-env envMode=test webpack --config build/webpack.prod.conf.js --color" },
- Cross env: run scripts that set up and use environment variables across platforms
- – config: which configuration file to use
- – color: turns on the console color
5 es6=>es5
//Installing babel yarn add @babel/core @babel/preset-env babel-loader -D yarn add core-js -S
5.1 matching js for conversion
//webpack.rules.conf.js module.exports = function (proMode) { return [{ test: /\.(t|j)s$/, exclude: /node_modules/, use: { loader: "babel-loader", options: { cacheDirectory: true } } }, ] }
5.2 install TypeScript and convert using babel
//Install ts yarn add typescript -D // Parsing babel pre for typescript yarn add @babel/preset-typescript -D //polyfill arrow function yarn add @babel/plugin-transform-runtime -D //Support the writing of ts class yarn add @babel/plugin-proposal-class-properties -D //Support three-point expansion yarn add @babel/plugin-proposal-object-rest-spread -D yarn add @babel/runtime @babel/runtime-corejs3 core-js -S
5.3 create babel.config.js
const presets = [ [ "@babel/preset-env", { "useBuiltIns": "usage", "corejs": "3.19.1" } ], [ '@babel/preset-typescript', // Reference Typescript plugin { allExtensions: true, // All file extensions are supported, otherwise using ts in vue file will report an error }, ], ] const plugins = [ //Introducing vant components on demand [ "import", { "libraryName": "vant", "libraryDirectory": "es", "style": true }, "vant" ], [ '@babel/plugin-transform-runtime', { corejs: 3, }, ], '@babel/proposal-class-properties', '@babel/proposal-object-rest-spread', ] module.exports = { plugins, presets }
6 automatically generate HTML files
yarn add html-webpack-plugin -D
6.1 HTML webpack plugin configuration
//webpack.base.conf.js const HtmlWebpackPlugin = require("html-webpack-plugin"); const cdn = { dev: { css: [], js: [] }, prod: { css: [], js: [ 'https://lib.baomitu.com/vue/3.0.11/vue.runtime.global.prod.js', "https://lib.baomitu.com/vue-router/4.0.6/vue-router.global.prod.min.js", "https://lib.baomitu.com/vuex/4.0.0/vuex.global.prod.min.js" ] } } module.exports = function (proMode) { return { plugins: [ new HtmlWebpackPlugin({ template: path.resolve(__dirname, "../public/index.html"), //Reference template location filename: "index.html", //The generated html path is relative to output.path title: "webpack+vue3", minify: { collapseWhitespace: true, //Collapse blank preserveLineBreaks: false, minifyCSS: true, //Compress minifyJS: true, removeComments: false }, files: proMode ? cdn.prod : cdn.dev }), ], } }
6.2 create a public folder and create index.html in it
// public/index.html //The content in the < title > tag in the template needs to be changed to <%= htmlWebpackPlugin.options.title %> //CDN introduction js <% for (var i in htmlWebpackPlugin.options.files&&htmlWebpackPlugin.options.files.js) { %> <script src="<%= htmlWebpackPlugin.options.files.js[i] %>"></script> <% } %>
7 add css support and less support
//css loader extracts the contents of. css //Style loader stores the content of. css according to the string in javascript. When the web page executes javascript, it dynamically inserts the style tag into the HTML HEAD tag through DOM operation yarn add style-loader css-loader -D yarn add less less-loader -D yarn add autoprefixer postcss-loader -D
7.1 using loader configuration
//webpack.rules.conf.js module.exports = function (proMode) { return [ { test: /\.less/, use: [MiniCssExtractPlugin.loader, "css-loader", { loader: "postcss-loader", options: { postcssOptions: { ident: "postcss", plugin: () => { require("postcss-preset-env")() } } } }, "less-loader" ] }, { test: /\.css$/, use: [ // "style-loader", MiniCssExtractPlugin.loader, "css-loader", { loader: "postcss-loader", options: { postcssOptions: { ident: "postcss", plugin: () => { require("postcss-preset-env")() } } } }, // "less-loader" ] } ] }
The loader executes from back to front
8. Configure alias alias and extension
//webpack.base.conf.js resolve: { alias: { "@": path.resolve(__dirname, "../src") }, //Extension writing //Write all the extensions in the project, otherwise an error will be reported extensions: [".js", ".vue", ".ts"] },
9. Clear the dist directory last built during packaging
//webpack.base.conf.js output: { clean: true },
10 identify. vue files
yarn add vue-loader@next @vue/compiler-sfc -D yarn add vue@next -S
- vue loader: parse and transform the. vue file and extract the js/style/html template
- @Vue / compiler SFC and Vue loader are called to convert the file content into webpack modular import form and AST abstract syntax tree
10.1 configuring matching rules
// webpack.rules.conf.js rules: [ { test: /\.vue$/, use: [ 'vue-loader' ] } ] //webpack.base.conf.js const { VueLoaderPlugin } = require('vue-loader/dist/index'); plugins: [ new VueLoaderPlugin() ]
10.2 add App.vue
<template> <div id="app"> <div id="nav" v-if="!$route.meta.hide"> <router-link to="/">Home</router-link>| <router-link to="/about">About</router-link> </div> <keep-alive> <router-view v-if="$route.meta.keepAlive" class="router" ></router-view> </keep-alive> <router-view v-if="!$route.meta.keepAlive" class="router"></router-view> </div> </template> <script> import { defineComponent, computed } from "vue"; import { useStore } from "vuex"; export default defineComponent({ setup() { const store = useStore(); return { title: computed(() => store.state.title), }; }, }); </script> <style lang="less"> // @import "style/_variables.scss"; #app { // font-family: "Avenir", Helvetica, Arial, sans-serif; // -webkit-font-smoothing: antialiased; // -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; } #nav { padding: 20px 0; a { font-weight: bold; color: #2c3e50; font-size: 32px; &.router-link-exact-active { color: red; } } } h3 { font-size: 18px; } a { } </style>
10.3 modify main.ts
import { createApp } from 'vue' // Vue 3.x introduces vue import App from './App.vue' // Introduce APP page setup const app = createApp(App) // Initialize app through createApp app.mount('#app ') / / mount the page to the root node
10.4 create vue type declaration file
src/shims-vue.d.ts declare module "*.vue" { import type { DefineComponent } from "vue"; const component: DefineComponent<{}, {}, any>; export default component; }
10.5. Vue documents always report errors and declare that the documents are not effective
//tsconfig.js //If you add the path of the declaration file to include, you will not report an error "types": ["./src/shims-vue.d.ts"],
11. Install vue bucket
yarn add vue-router@4 vuex@next axios -S
12. Integration Vant
yarn add vant@next -S //On demand import yarn add babel-plugin-import -D // babel.config.js const plugins = [ ['import', { libraryName: 'vant', libraryDirectory: 'es', style: true }, 'vant'] ] //At the same time of scaffolding, we should distinguish between css files and less files //The vant component cannot be identified by using less loader, and an error will be reported
13. Identification picture
//webpack.conf.rules.js module.exports = function (proMode) { return [ { test: /\.(png|jpg|svg|gif)$/, type: "asset/resource", generator: { filename: "assets/[hash:8].[name][ext]" } }, ] }
optimization
1. Output the static file to the packaging directory
//When using the copy webpack plugin, the folder to be copied cannot be empty, otherwise an error will be reported yarn add copy-webpack-plugin -D //webpack.prod.conf.js const copyWebpackPlugin = require("copy-webpack-plugin"); const webpackConfigProd = { mode: "production", plugins: [ new copyWebpackPlugin({ patterns: [{ from: path.resolve(__dirname, "../public"), to: "./", globOptions: { dot: true, gitignore: true, ignore: ["**/index.html"], } }] }), ], }
2. Extract style file
yarn add mini-css-extract-plugin -D //webpack.base.conf.js const miniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = function (proMode) { return { plugins: [ new miniCssExtractPlugin({ filename: "./css/[name].[contenthash].css", }), ], } } //webpack.rules.conf.js const MiniCssExtractPlugin = require('mini-css-extract-plugin') module.exports = function (proMode) { return [ { test: /\.less/, use: [MiniCssExtractPlugin.loader, "css-loader", { loader: "postcss-loader", options: { postcssOptions: { ident: "postcss", plugin: () => { require("postcss-preset-env")() } } } }, "less-loader" ] }, { test: /\.css$/, use: [ // "style-loader", MiniCssExtractPlugin.loader, "css-loader", { loader: "postcss-loader", options: { postcssOptions: { ident: "postcss", plugin: () => { require("postcss-preset-env")() } } } }, // "less-loader" ] } ] }
3. vw adaptation
yarn add postcss-loader postcss-px-to-viewport -D //Create a new postcss.config.js file const path = require("path") module.exports = ({ file }) => { const designWidth = file.includes(path.join("node_modules", "vant")) ? 375 : 750; return { plugins: { autoprefixer: { overrideBrowserslist: [ "Android 4.1", "iOS 7.1", "Chrome > 31", "ff > 31", "ie >= 8" ] }, "postcss-px-to-viewport": { unitToConvert: 'px', // The unit to be converted is "px" by default viewportWidth: designWidth, // Viewport width of the design unitPrecision: 5, // Precision retained after unit conversion propList: ['*'], // List of attributes that can be converted to vw viewportUnit: 'vw', // The viewport units you want to use fontViewportUnit: 'vw', // The viewport units used by the font selectorBlackList: ['.ignore', '.hairlines', '.ig-'], // CSS selectors that need to be ignored minPixelValue: 1, // The smallest conversion value. If it is 1, only values greater than 1 will be converted mediaQuery: false, // Does the unit in the media query need to be converted replace: true, // Whether to directly replace the attribute value without adding an alternate attribute include: undefined, // If include is set, only the matched files will be converted, for example, only the files under 'src/mobile' (include: /\/src\/mobile \ / /) landscape: false, // Add media query condition @ media (orientation: landscape) generated according to landscape width landscapeUnit: 'vw', // Units used when horizontal screen landscapeWidth: 568 // The width of the viewport used when the screen is horizontal } } } }
4. Remove the console from the production environment
//webpack.prod.conf.js const TerserPlugin = require('terser-webpack-plugin'); const webpackConfigProd = { mode: "production", optimization: { minimize: true, minimizer: [ new TerserPlugin({ parallel: true, extractComments: false, terserOptions: { compress: { drop_console: true, drop_debugger: true } } }), ] } }
5. Cache
//webpack.base.conf.js module.exports = function (proMode) { return { cache: { type: "filesystem", buildDependencies: { config: [__filename] } }, } }