webpack configuration - related property description

Welcome to click to follow-advanced guide for front-end interviews: front-end to the top-the most comprehensive summary of front-end knowledge points

Preface: webpack is the most common module packaging tool for our modern front-end. webpack is a module packager whose main purpose is to package JavaScript files on the browser. Features: Bundles CommonJs and AMD modules (and bindings), creates single or multiple on-demand chunks to reduce initial load time, dependencies are resolved during compile time, reduces runtime size, loader can be used in Preprocess files at compile time, such as coffee-script to javascript.

The editor also builds webpack from zero in his spare time, as a demonstration to explain some commonly used function blocks and attribute methods

insert image description here
Learn about the Bable js compiler

Webpack advanced - custom plug-in principle

80% reduction in volume! Unleash the true potential of webpack tree-shaking

package.json file description

Relevant attributes depend on the version number, which is not the latest version. Please reinstall the dependencies for actual development

{
    
    
  //从name到private都是package的配置信息,也就是我们在脚手架搭建中输入的项目描述
  "name": "shop",//项目名称:不能以.(点)或者_(下划线)开头,不能包含大写字母,具有明确的的含义与现有项目名字不重复
  "version": "1.0.0",//项目版本号:遵循“大版本.次要版本.小版本”
  "description": "webpack project",//项目描述
  "author": "njt",//作者名字
  "private": true,//是否私有
  "scripts": {
    
     //scripts中的子项即是我们在控制台运行的脚本的缩写
   //①webpack-dev-server:启动了http服务器,实现实时编译;
   //inline模式会在webpack.config.js入口配置中新增webpack-dev-server/client?http://localhost:8080/的入口,使得我们访问路径为localhost:8080/index.html(相应的还有另外一种模式Iframe);
   //progress:显示打包的进度
    "start": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",  
    "start": "npm run dev",//与npm run dev相同,直接运行开发环境
    "build": "node build/build.js"//使用node运行build文件
    "analyz": "NODE_ENV=production npm_config_report=true npm run build", // 查看打包体积大小分布
  },
  "dependencies": {
    
     //②dependencies(项目依赖库):在安装时使用--save则写入到dependencies
    "vue": "^2.5.2",//vue.js
    "vue-router": "^3.0.1"//vue的路由插件
  },
  //和devDependencies(开发依赖库):在安装时使用--save-dev将写入到devDependencies
  "devDependencies": {
    
    
    "autoprefixer": "^7.1.2",//autoprefixer作为postcss插件用来解析CSS补充前缀,例如 display: flex会补充为display:-webkit-box;display: -webkit-flex;display: -ms-flexbox;display: flex。
    //babel:以下几个babel开头的都是针对es6解析的插件。用最新标准编写的 JavaScript 代码向下编译成可以在今天随处可用的版本
    "babel-core": "^6.22.1",//babel的核心,把 js 代码分析成 ast ,方便各个插件分析语法进行相应的处理。
    "babel-helper-vue-jsx-merge-props": "^2.0.3",//预制babel-template函数,提供给vue,jsx等使用
    "babel-loader": "^7.1.1",//使项目运行使用Babel和webpack来传输js文件,使用babel-core提供的api进行转译
    "babel-plugin-syntax-jsx": "^6.18.0",//支持jsx
    "babel-plugin-transform-runtime": "^6.22.0",//避免编译输出中的重复,直接编译到build环境中
    "babel-plugin-transform-vue-jsx": "^3.5.0",//babel转译过程中使用到的插件,避免重复
    "babel-preset-env": "^1.3.2",//转为es5,transform阶段使用到的插件之一
    "babel-preset-stage-2": "^6.22.0",//ECMAScript第二阶段的规范
    "chalk": "^2.0.1",//用来在命令行输出不同颜色文字
    "copy-webpack-plugin": "^4.0.1",//拷贝资源和文件
    "css-loader": "^0.28.0",//webpack先用css-loader加载器去解析后缀为css的文件,再使用style-loader生成一个内容为最终解析完的css代码的style标签,放到head标签里
    "mini-css-extract-plugin": "^0.9.0",//将一个以上的包里面的css文本提取到单独文件中
    "file-loader": "^1.1.4",//③打包压缩文件,与url-loader用法类似
    "friendly-errors-webpack-plugin": "^1.6.1",//识别某些类别的WebPACK错误和清理,聚合和优先排序,以提供更好的开发经验
    "html-webpack-plugin": "^2.30.1",//简化了HTML文件的创建,引入了外部资源,创建html的入口文件,可通过此项进行多页面的配置
    "node-notifier": "^5.1.2",//支持使用node发送跨平台的本地通知
    "ora": "^1.2.0",//加载(loading)的插件
    "portfinder": "^1.0.13",//查看进程端口
    "postcss-import": "^11.0.0",//可以消耗本地文件、节点模块或web_modules
    "postcss-loader": "^2.0.8",//用来兼容css的插件
    "postcss-url": "^7.2.1",//URL上重新定位、内联或复制
    "webpack-parallel-uglify-plugin": "^1.1.2",//压缩js文件
    "url-loader": "^0.5.8",//压缩文件,可将图片转化为base64
    "vue-loader": "^13.3.0",//VUE单文件组件的WebPACK加载器
    "vue-style-loader": "^3.0.1",//类似于样式加载程序,您可以在CSS加载器之后将其链接,以将CSS动态地注入到文档中作为样式标签
    "vue-template-compiler": "^2.5.2",//这个包可以用来预编译VUE模板到渲染函数,以避免运行时编译开销和CSP限制
    "webpack": "^4.43.0",//打包工具
    "webpack-cli": "^3.3.12",
    "webpack-bundle-analyzer": "^2.9.0",//可视化webpack输出文件的大小
    "webpack-dev-server": "^3.11.0",//提供一个提供实时重载的开发服务器
    "webpack-merge": "^4.2.2"//它将数组和合并对象创建一个新对象。如果遇到函数,它将执行它们,通过算法运行结果,然后再次将返回的值封装在函数中
  },
  "engines": {
    
     //engines是引擎,指定node和npm版本
    "node": ">= 6.0.0",
    "npm": ">= 3.0.0"
  },
  "browserslist": [ //限制了浏览器或者客户端需要什么版本才可运行
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
}

1. Code example webpack.base.js public compilation module: entry, exit, compilation module configuration, code block segmentation, performance warning, plug-in, etc.

const os = require('os')
const path = require('path');
const webpack = require('webpack');
const HappyPack = require('happypack')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {
    
     CleanWebpackPlugin } = require('clean-webpack-plugin'); // webpack4官网未同步,改变了引用方式
const MiniCssExtractPlugin = require("mini-css-extract-plugin")

const happyThreadPool = HappyPack.ThreadPool({
    
    
  size: os.cpus().length
})
module.exports = {
    
    
  entry: {
    
     // 项目编译的文件入口地址,也是配置多文件入口地址
    main: './src/index.js',
  },

  output: {
    
     // 项目编译文件的出口地址
  	// 编译生成的js文件存放在根目录下的js目录下,如果js文件夹不存在就自动创建
    filename: 'js/[name].[chunkhash].js', // 「入口分块(entry chunk)」的文件名模板(出口分块)
    path: path.resolve(__dirname, '../dist'), // 所有输出文件的目标路径
    publicPath: "/assets/", // 输出解析文件的目录,url 相对于 HTML 页面
	// 常用与封装第三方库使用,项目内注释掉
	// library: "MyLibrary", // 导出库(exported library)的名称
    // libraryTarget: "umd", // 通用模块定义
  },

  resolve: {
    
     // 解析模块请求的选项
    extensions: [".js", ".json", ".jsx", ".css"], // 使用的扩展名
    alias: {
    
      // 模块别名列表
      '@': path.resolve(__dirname, '../src')
    }
  },
   
  module: {
    
    
    rules: [
      {
    
    
        test: /\.js$/, // 这里是匹配条件,每个选项都接收一个正则表达式或字符串
        loader: 'happypack/loader?id=happyBable', // 应该应用的 loader,它相对上下文解析
        exclude: /node_modules\/(?!module-[^\s]+)/, // exclude 是必不匹配选项(优先于 test 和 include)
        include: [
          path.resolve(__dirname, '../src'),
          path.resolve(__dirname, 'node_modules/webpack-dev-server/client'),
          /module-[^\s]+/i,
        ]
      },
      {
    
    
        test: /\.css$/,
        use: ['style-loader', MiniCssExtractPlugin.loader, 'css-loader']
      },
      {
    
    
        test: /\.(png|svg|jpg|gif)$/,
        use: ['file-loader']
      },
      {
    
    
        test: /\.(woff|woff2|eot|ttf|otf)$/,
        use: ['file-loader']
      }
    ]
  },

  optimization: {
    
     // 代码分割文件依赖公共模块部分
    splitChunks: {
    
    
      chunks: "all",   //initial、async和all
      minSize: 30000,   //形成一个新代码块最小的体积
      minChunks: 2,  //在分割之前,这个代码块最小应该被引用的次数
      maxAsyncRequests: 5,   //按需加载时候最大的并行请求数
      maxInitialRequests: 3,   //最大初始化请求数
      automaticNameDelimiter: '~',   //打包分割符
      name: 'commons', //打包后的名字
     // 会抽离出第三库的代码,生成一个vendors.db5b3f3dc26a5ebe685c.js文件,且每次打包第三库的hash也不会变化,
    // 这样就会利用浏览器的缓存机制,达到一个缓存优化,除非第三方库的版本变化,会重新生成一个新的文件,这样浏览
    // 器也会重新请求新的文件。
      cacheGroups: {
    
    
        vendors: {
    
    
          test: /[\\/]node_modules[\\/]/,   //用于控制哪些模块被这个缓存组匹配到、它默认会选择所有的模块
          priority: -10,   //缓存组打包的先后优先级
          name: 'vendors',
          minSize: 3000
        },
        styles: {
    
    
          name: 'styles',
          test: /\.(c|le)ss$/,
          chunks: 'all',
          enforce: true,
        },
        default: {
    
    
          minChunks: 2,
          priority: -20,
          minSize: 3000
        }
      }
    },
  },

  performance: {
    
     // 性能提示
	maxEntrypointSize: 2.5 * 1024 * 1024, // 整数类型(以字节为单位)
	maxAssetSize: 3 * 1024 * 1024 // 整数类型(以字节为单位)
  },

  plugins: [
    new CleanWebpackPlugin(), // 在每次构建前清理 /dist 文件夹。
    new HtmlWebpackPlugin({
    
     // 为您生成HTML文件,其余参数详看https://github.com/jantimon/html-webpack-plugin
      inject: 'body',
      minify: {
    
     // 压缩html
        removeComments: true,
        collapseWhitespace: true,
        removeAttributeQuotes: true
      },
      template: path.resolve(__dirname, '../index.html')
    }),
    new HappyPack({
    
     // 将文件解析任务分解成多个子进程并发执行
      id: 'happyBable',  // id 标识符,要和 rules 中指定的 id 对应起来
      loaders: ['babel-loader?cacheDirectory'], // babel-loader开启缓存;需要使用的 loader,用法和 rules 中 Loader 配置一样
      threadPool: happyThreadPool, // 对象,代表共享进程池, 以防止资源占用过多
      verbose: true // 是否允许 happypack 输出日志,默认是 true
    }),
    new MiniCssExtractPlugin({
    
     // 为每个包含 CSS 的 JS 文件创建一个单独的 CSS 文件,并支持 CSS 和 SourceMap 的按需加载
      filename: "css/[name].[chunkhash].css",
      ignoreOrder: false,
    })
  ],
};

Supplement: The MiniCssExtractPlugin plug-in extracts the css file in the js file and imports it in the index.html file with a link. Note: when the style-loader and css-loader methods do not take effect in the production environment, the reason: 1. Whether to enable the tree Shaking, remove "sideEffects" in the package.json file or change it to your own matching file; 2. Check whether the loader configured in the rules is correct. The MiniCssExtractPlugin plug-in does not support style-loader. 3. After configuring the MiniCssExtractPlugin plug-in, multiple bundle.css packages will be generated, which can be packaged into a single file by configuring cacheGroups.

2. Code example webpack.dev.js development environment compilation modules: mode, devServer, plugins, etc.

const ip = require('ip') // 获取本地ip地址
const path = require('path')
const merge = require('webpack-merge'); // 在环境特定配置 merge() 合并 dev 和 prod常见配置
const common = require('./webpack.base.js'); // 编译环境公共模板
const packageConfig = require('../package.json')
const CopyWebpackPlugin = require('copy-webpack-plugin') // 拷贝静态文件资源
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');

const devConfig = {
    
    
  mode: 'development', // 环境区分:"production" | "development" | "none"
  devtool: 'inline-source-map', // 通过在浏览器调试工具(browser devtools)中添加元信息(meta info)增强调试,详细配置请点击https://www.webpackjs.com/configuration/devtool/
  devServer: {
    
    
    contentBase: '../dist', // 服务的访问地址,也是你本地编译完后的访问地址
    port: 8081, // 端口的位置
    quiet: true, // 关闭编译终端出错,这与FriendlyErrorsWebpackPlugin相关联,控制台编译出错
    overlay: true, // 编译出现错误时,将错误直接显示在页面上
    historyApiFallback: {
    
     // 404响应页面 默认index.html
      rewrites: [{
    
    
        from: /.*/,
        to: path.posix.join('/', '../index.html')
      }, ],
    }
  }
};

// 启动消息提示在终端显示
const createNotifierCallback = () => {
    
    
  const notifier = require('node-notifier')
  return (severity, errors) => {
    
    
    if (severity !== 'error') return false;
    const error = errors[0]
    const filename = error.file && error.file.split('!').pop()
    notifier.notify({
    
    
      title: packageConfig.name,
      message: severity + ': ' + error.name,
      subtitle: filename || '',
      icon: path.join(__dirname, 'logo.png'),
      sound: true
    })
  }
}

module.exports = merge(common, devConfig, {
    
    
  plugins: [
    new FriendlyErrorsWebpackPlugin({
    
     // 去除终端webpack多余编译信息使界面可观
      compilationSuccessInfo: {
    
    
        messages: [`Your application is running here: http://${
      
      ip.address()}:${
      
      devConfig.devServer.port}`],
      },
      onErrors: () => createNotifierCallback(),
      clearConsole: true,
    }),
     new CopyWebpackPlugin({
    
    
      patterns: [
        {
    
    
          from: path.resolve(__dirname, '../static'),
          to: "static"
        }
      ]
    }),
  ]
})
  • FriendlyErrorsWebpackPlugin removes redundant compilation information of terminal webpack to make the interface impressive
    insert image description here

3. Code example webpack.prod.js production environment compilation modules: mode, devtool, plugins, etc.

const webpack = require('webpack');
const merge = require('webpack-merge');
const common = require('./webpack.base.js');
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = merge(common, {
    
    
  mode: 'production', // 生产环境,默认开启更小的代码量以加快网页的加载速度,对源代码进行压缩
  devtool: false,
  plugins: [
    new webpack.DefinePlugin({
    
     //自定义一个plugin 生成当前环境下的一个变量
      'process.env.NODE_ENV': JSON.stringify('production')
    }),
    new ParallelUglifyPlugin({
    
     // 使用 ParallelUglifyPlugin 并行压缩输出的 JS 代码
      uglifyJS: {
    
      // 传递给 UglifyJS 的参数
        output: {
    
    
          // 最紧凑的输出
          beautify: false,
          // 删除所有的注释
          comments: false,
        },
        warnings: false,  // 在UglifyJs删除没有用到的代码时不输出警告
        compress: {
    
    
          // 删除所有的 `console` 语句,可以兼容ie浏览器
          drop_console: true,
          // 内嵌定义了但是只用到一次的变量
          collapse_vars: true,
          // 提取出出现多次但是没有定义成变量去引用的静态值
          reduce_vars: true,
        }
      },
    }),
    new BundleAnalyzerPlugin()
  ]
});

4. Supplementary knowledge point Chunk understands that
Chunk refers to a code block in webpack. For modules, Webpack can be regarded as a module packer. Any file we write is a module for Webpack. Chunk is a collection of modules in the webpack packaging process. Chunk and Bundle, Bundle is one or more packaged files that we finally output. There are three ways to generate Chunk: entry entry, asynchronous loading of modules, and code splitting.

5. The principle of webpack hot update:

  1. During Webpack compilation, inject hot update code for the entry that needs hot update (EventSource communication)
  2. After the page is opened for the first time, the server and the client establish a communication channel through EventSource, and return the next hash to the front end
  3. The client gets the hash, and this hash will be used as the hash of the next request server-side hot-update.js and hot-update.json
  4. After modifying the page code, Webpack will start compiling after listening to the modification of the file. After compiling, it will send a build message to the client
  5. The client obtains the hash, and after success, the client constructs a hot-update.js script link, and then inserts it into the main document
  6. After hot-update.js is successfully inserted, execute the createRecord and reload methods of hotAPI, get the render method of the Vue component, re-render the component, and then realize the update without refreshing the UI.

5. Webpack compilation principle

  1. Initialization parameters: read and combine parameters from configuration files and Shell statements to obtain final parameters;
  2. Start compiling: initialize the Compiler object with the parameters obtained in the previous step, load all configured plug-ins, and execute the run method of the object to start compiling;
  3. Determine the entry: Find all entry files according to the entry in the configuration;
  4. Compile the module: start from the entry file, call all configured Loaders to translate the module, find out the modules that the module depends on, and then recurse this step until all the files that the entry depends on have been processed by this step;
  5. Complete module compilation: After translating all modules using Loader in step 4, the final translated content of each module and the dependencies between them are obtained;
  6. Output resources: According to the dependencies between the entry and the modules, assemble them into chunks containing multiple modules, and then convert each chunk into a separate file and add it to the output list. This step is the last chance to modify the output content ;
  7. Output completion: After determining the output content, determine the output path and file name according to the configuration, and write the file content to the file system.

This article only makes relevant comments on the attributes commonly used by webpack. Related articles in the actual development also explain it. If you often knock on it, you will encounter some uncommon problems. It is also a help for growth! Always check the official website for other attributes and plug-ins.
Finally, I recommend an article on how webpack realizes dynamic import

Guess you like

Origin blog.csdn.net/weixin_43624724/article/details/107251947