1, What are the main links in the Webpack construction process? If you can, please describe the whole process of Webpack packaging in as much detail as possible
1. Initialization item, initialization parameters: according to different parameters configured by the user
2. Initialization parameters. The final configuration is obtained according to the parameters entered by the user in the command window and the configuration of webpack.config.js
3. Start compiling, initialize a compiler object according to the last configuration parameters obtained in the previous step, register all plug-in plugin s, and the plug-in starts listening to the construction process of webpack,
Different links will correspond to the corresponding processing, and then start compiling.
3. Determine the entry. According to the entry entry in webpack.config.js, start parsing the file, build the AST syntax tree, and find out the dependencies.
4. The compilation module, in the recursive process, calls the corresponding loader to perform different conversion processing on different files according to the file type and loader configuration. Then find out the modules that the module depends on,
Until all the modules that the project depends on have been compiled
5. After compiling and outputting and recursion, get the results of each file, including the converted modules and their dependencies, and generate code blocks according to the configuration of entry and output,
The dist directory will be clear before the end.
6. After packaging, output to the specified directory according to output.
2. What are the differences between Loader and Plugin? Please describe the idea of developing Loader and Plugin.
1, Loader is directly translated as "loader", which is mainly used to parse and detect the corresponding resources and is responsible for the conversion of source files from input to output. It focuses on the loading of resource modules.
Handle some codes that are not supported or compatible with the browser as resources that the browser can support. For example, convert ES6 + to ES5 and Sass recognized by the browser to css.
1. Export a function through moudule.exports
2. The default parameter of this function is the first parameter source (i.e. the resource file to be processed)
3. Process resources in the function body (after the Loder of the response is configured in the Loder)
4. Return the last packaged result through return (the returned result here needs to be in string format)
2, Plugin mainly performs some additional work at different stages of webpack construction, such as copying static resources, emptying packaged folders, etc.
1. Through hook mechanism
2. The plug-in must be a function or an object containing an apply method
3. In the method body, obtain resources through the API provided by webpack for response processing
4. Return the processed resource to the resource through the method provided by webpack
## webpack.common.js // const path = require('path') const resolveApp = require('./paths') const HtmlWebpackPlugin = require('html-webpack-plugin') // Packaging is the automatic creation of html const TerserPlugin = require("terser-webpack-plugin") // Code splitting, loading and packaging to remove unnecessary files const { merge } = require('webpack-merge') const MiniCssExtractPlugin = require("mini-css-extract-plugin") // time analysis const SpeedMeasurePlugin = require("speed-measure-webpack-plugin") const smp = new SpeedMeasurePlugin() // Import other configurations const prodConfig = require('./webpack.dev') const devConfig = require('./webpack.dev') // Define object to save base configuration information const commonConfig = { entry: './src/main.js', // Compile target resource file devtool: 'source-map', // Code mapping, locating the error location // The inline column reports an error, and the soap improves efficiency by removing empty rows. The original soap module is restored. resolve: { extensions: [".js", ".json", ".ts", ".jsx", ".vue"], // Match the path after the route and omit the file format suffix alias: { // '@': path. Resolve (_dirname, '.. / SRC') / / matches the path after the route, omitting the path before the path/ '@': resolveApp('./src') } }, output: { filename: 'js/build.js', // Output the file name and put it separately in the js directory // filename: 'js/[name].build.js', / / code splitting and packaging, dynamic file name // Path. Resolve (_dirname, '.. / dist'), / / output folder path: resolveApp('./dist'), publicPath: '/lg' // Relative path or absolute path, address directory }, externals: { // Introducing CDN lodash: '_' // Naming after introduction }, optimization: { minimizer: [ new TerserPlugin({ extractComments: false, }), ], splitChunks: { chunks: 'all', // Support asynchronous and synchronous all minSize: 20000, // file size maxSize: 20000, minChunks: 1, cacheGroups: { syVendors: { test: /[\\/]node_modules[\\/]/, filename: 'js/[id]_vendor.js', // filename can be dynamic, and name can only be written to death priority: -10, }, default: { // Number of visits minChunks: 2, filename: 'js/syy_[id].js', priority: -20, } } } }, module: { // Resource module rules: [ // rule { test: /\.css$/, use: [ 'style-loader', { loader: 'css-loader', options: { // The postcss loader does not check the code that needs to be compatible. If it is checked by CSS loader, you can go back one step importLoaders: 1 } }, { loader: 'postcss-loader', // js conversion style tool. You need to install postcss and postcss cli options: { // configuration parameter postcssOptions: { plugins: [ // Required plug-ins require('autoprefixer'), require('postcss-preset-env') // Handle css compatibility issues, including autoprefixer ] } } }, { test: /\.(png|svg|gif|jpe?g)$/, // Processing pictures // use: [ // { // loader: 'file-loader', // options: { // name: 'img/[name].[hash:6].[ext]', / / specify the path and name for the picture (path / name. Hasi 6 bits. Suffix) // limit: 25 * 1024 / / picture size // } // } // ] type: 'asset', generator: { filename: 'img/[name].[hash:6].[ext]' }, parser: { // analysis dataUrlCondition: { maxSize: 30 * 1024 } } }, { test: /\.(ttf|woff2?)$/, // Processing fonts type: 'asset/resource', generator: { filename: 'font/[name].[hash:3][ext]' } } ] }, { test: /\.less$/, use: [ 'style-loader', 'css-loader', 'postcss-loader', // The principle is the same as above, and the postcss loader file is called externally 'less-loader' ] }, { test: /\.js$/, // Use bable loader to convert es6 syntax use: ['bable-loader'] }, { test: /\.jsx?$/, // react hot update use: ['babel-loader'] }, { test: /\.vue$/, // vue hot update use: ['vue-loader'] }, { test: /\.ts$/, use: ['bable-loader'] }, { test: /\.css$/, // Pull off css use: [ isProduction ? MiniCssExtractPlugin.loader : 'style-loader', { loader: 'css-loader', options: { importLoaders: 1, esModule: false } }, 'postcss-loader' ] }, ] }, plugins: [ // plug-in unit new HtmlWebpackPlugin({ title: 'html-webpack-plugin', // html internal title template: './public/index.html' // html template path }) ] } module.exports = (env) => { const isProduction = env.Production process.env.NODE_ENV = isProduction ? 'prodConfig' : 'development' // Merge configurations according to the current packaging mode const config = isProduction ? prodConfig : devConfig const mergeConfig = merge(commonConfig, config) return mergeConfig return smp.wrap(mergeConfig) } ## webpack.dev.js const VueLoaderPlugin = require('vue-loader/lib/plugin') module.exports = { mode: 'development', // development environment devtool: 'cheap-module-source-map', // Code mapping, locating the error location // When an error is reported in the inline column, the soap improves efficiency and removes empty rows. The original soap module is restored. target: 'web', // Mask browser compatibility devServer: { // The configuration related to webpack dev serve is written here hot: true, // Turn on hot update publicPath: '/lg', // Consistent with the publicPath in output, find the resource target contentBase: path.resolve(__dirname, 'public'), watchContentBase: true, hotOnly: true, // Error message before refresh (one component is not affected by other components) port: 4000, // port open: false, // Open a new page compress: true, // Compress the current file historyApiFallback: true, // Route switching 404 proxy: { // Solve cross domain '/api': { target: 'https://api.github.com ', / / ask who wants pathRewrite: { "^/api": "" }, changeOrigin: true } } }, plugins: [ // plug-in unit new VueLoaderPlugin() ] } ## Title webpack.prod const { CleanWebpackPlugin } = require('clean-webpack-plugin') // Clear dist plug-in const CopyWebpackPlugin = require('copy-webpack-plugin') // Copy const CssMinimizerPlugin = require("css-minimizer-webpack-plugin") const TerserPlugin = require("terser-webpack-plugin") // Compress js // const webpack = require('webpack') const PurgeCSSPlugin = require('purgecss-webpack-plugin') const resolveApp = require('./paths') const glob = require('glob') const CompressionPlugin = require("compression-webpack-plugin") // Compressed resources const InlineChunkHtmlPlugin = require('inline-chunk-html-plugin') // Inject js code const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { mode: 'production', // production environment optimization: { // usedExports: true, / / mark code execution (Mark unused content in the code) minimize: true, minimizer: [ new CssMinimizerPlugin(), new TerserPlugin({ extractComments: false }) ] }, plugins: [ // plug-in unit new CleanWebpackPlugin(), // Clear dist new CopyWebpackPlugin({ patterns: [ // { from: 'public', // Where to start the copy, the target directory. You can omit to and find the path directory under output by default globOptions: { // Ignore something ignore: ['**/index.html'] // **/Indicates to search from public } } ] }), // new webpack.optimize.ModuleConcatenationPlugin() new PurgeCSSPlugin({ paths: glob.sync(`${resolveApp('./src')}/**/*`, { nodir: true }), // Keep files and remove directories safelist: function () { return { standard: ['body', 'html', 'ef'] } } }), new CompressionPlugin({ test: /\.(css|js)$/, minRatio: 0.8, threshold: 0, // Compression starts when the volume is greater than 0 algorithm: 'gzip' // Browser supported compression algorithms }), new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime.*\.js/]) // Inject js code into html ] } ## paths.js // Path module // Search according to the current config directory const path = require('path') const appDir = process.cwd() console.log(appDir, '<---') const resolveApp = (relativePath) => { return path.resolve(appDir, relativePath) } module.exports = resolveApp ## babel.config.js // bable's configuration is used to convert js code // module.exports = { // presets: [ // '@babel/preset-env', // {/ / polyfill fills in plug-ins with insufficient babel functions // //false: the current js processing will not be filled with polyfill // //usage: fill in according to the new syntax used in the user's source code // //entry: decide what to fill based on the currently filtered browser // useBuiltIns: 'entry', // Corejs: 3 / / corejs version is 3 // } // ] // } const presets = [ [ '@babel/preset-env', { // polyfill fills in plug-ins with insufficient babel functionality // false: the current js processing will not be filled with polyfill // usage: fill in according to the new syntax used in the user's source code // entry: decide what to fill based on the currently filtered browser useBuiltIns: 'entry', corejs: 3 // corejs version 3 } ], [ '@babel/preset-react' ] ] const plugins = [] console.log(process.env.NODE_ENV, '<-----') // The value of plugins is determined according to the current packaging mode const isProduction = process.env.NODE_ENV === 'production' if (!isProduction) { plugins.push(['react-refresh/babel']) } module.exports = { presets, plugins } ## postcss.config.js module.exports = { plugins: [ require('postcss-preset-env') ] } ## Server.js const express = require('express') const webpackDevMiddleware = require('webpack-dev-middleware') const webpack = require('webpack') const app = express() // Get profile const config = require('./webpack.common.js') const compiler = webpack(config) app.use(webpackDevMiddleware(compiler)) // Turn on the service on the port app.listen(3000, () => { console.log('The service runs on port 3000') }) // function? // node .\Server.js ## .browserslistr > 1% last 2 version not dead ## babel.config.js module.exports = { presets: [ [ '@babel/preset-env', { userBuilIns: 'usage', // Code plug-in completion corejs: 3 // edition } ], ['@vue/cli-plugin-babel/preset'] ] } ## package.js { "name": "vue-app-base", "version": "0.1.0", "private": true, "scripts": { "serve": "webpack serve --config ./config/webpack.common.js --env development", "build": "webpack --config ./config/webpack.common.js --env production", "ck": "tsc --noEmit", "lint": "npm run serve" }, "sideEffects": [ "./src/title.js" ], "dependencies": { "core-js": "^3.6.5", "vue": "^2.6.11" }, "devDependencies": {}, "eslintConfig": { "root": true, "env": { "node": true }, "extends": [ "plugin:vue/essential", "eslint:recommended" ], "parserOptions": { "parser": "babel-eslint" }, "rules": {} }, "browserslist": [ "> 1%", "last 2 versions", "not dead" ], "description": "1. This is a use Vue CLI Created Vue Project infrastructure\r 2. The difference is that I removed it here vue-cli-service(contain webpack Black box tools such as tools)\r 3. The requirement here is to use it directly webpack And the surrounding tools you know Loader,Plugin Restore the packaging task for this project\r 4. Use all the features and functions you know as much as possible", "main": "babel.config.js", "keywords": [], "author": "", "license": "ISC" } ## .eslintrc.js // Eslint loader is configured in the development environment const commonConfig = require('./webpack.common') const merge = require('webpack-merge') const path = require('path') module.exports = merge(commonConfig,{ mode:'development', devtool:'cheap-module-eval-source-map', module:{ rules:[ { test: /\.js$/, exclude: /node_modules/, use: 'eslint-loader', enforce:'pre' }, ] }, devServer: { contentBase: path.join(__dirname, 'dist'), port: 9000, hot: true } })