image.png

webpack是什么

webpack是一个项目构建工具、它可以把你一些组织互相依赖的代码、按类别去帮你打包成一个整体唯一的文件、在打包中通过loader去处理webpack不认识的文件、在打包构建流程中抛出不同时期的生命周期钩子通知plugin、也可以在打包中往代码里面注入不同的环境变量、对代码的压缩配合其他插件(babel) 对源代码进行编译、编译成通用浏览器的语法、也可以在plugin里面对输出文件内容的做增删除、最重要的是这一系列的流程你并不需要写太多代码、你只需通过一个配置文件去定义你的打包规则、相对来说比较简单就能配置出一个基础环境!

webpack特点

  • 自身功能齐全、插件系统完善支持自定义loader和plugin、定制化强、扩展性强、面对复杂场景也是游刃有余、社区生态完整、业界应用工程化首选!

    搭建一个简单的webpakc环境

    安装webpack依赖

    1. // 初始化package.json
    2. yarn init
    3. // 安装webpack
    4. yarn add webpack webpack-cli -D
    5. // 在package.json里面配置打包命令
    6. "scripts": {
    7. "build":"webpack --config webpack.config.js"
    8. }

    创建webpack.config.js(打包配置文件)

    ```javascript // 根节点创建webpack.config.js const path = require(‘path’);

module.exports = { // 入口文件 entry: { ‘main’:’./src/main.js’, }, // 此选项控制是否生成,以及如何生成 source map。 devtool: ‘inline-source-map’, // 模式-环境 mode: ‘development’, module:{ // 模块配置相关(配置 loader、解析器等选项) rules:[

  1. ]
  2. },
  3. // 插件使用
  4. plugins: [],
  5. // 输出规则
  6. output: {
  7. // 输出的文件名、[name] 来自打包的名称
  8. filename: '[name].bundle.js',
  9. // 输出的位置
  10. path: path.resolve(__dirname, 'dist'),
  11. // 在生成文件之前清空 output 目录
  12. clean: true
  13. }

};

  1. > 创建一个src->main.js、然后在src下在创建一个test1.js test2.js、然后开始随便写点内容、下方的图就是依赖关系
  2. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/12473205/1648870957926-59da7271-a06b-4d7e-93c3-ccf43c8ce438.png#clientId=u5018bb80-69ba-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=724&id=u7a6a7989&margin=%5Bobject%20Object%5D&name=image.png&originHeight=796&originWidth=1279&originalType=binary&ratio=1&rotation=0&showTitle=false&size=560085&status=done&style=shadow&taskId=u5b2678ac-2125-41e5-9363-6e19b8b3e7f&title=&width=1162.7272475258383)
  3. <a name="wXcSD"></a>
  4. #### 执行yarn build 开始打包
  5. > 打包后我们在根节点创建一个public文件夹、并且里面创建一个index.html引入dist里面的js文件,然后在浏览器打开、我们发现里面输出了我们打包文件的内容信息、这样我们就完成了一个简单的打包!下面我们开始配置一些常用的loader和插件
  6. <a name="vh3r3"></a>
  7. #### 常用loader和plugin
  8. <a name="IqXhZ"></a>
  9. ##### loader
  10. - **style-loadercss-loader **
  11. ```javascript
  12. // 安装
  13. yarn add style-loader css-loader -D
  14. // webpack.config.js使用
  15. module: {
  16. // 模块配置相关(配置 loader、解析器等选项)
  17. rules: [
  18. {
  19. test: /\.css$/i,
  20. use: ["style-loader", "css-loader"],
  21. },
  22. ]
  23. }
  24. // 使用
  25. import "./style/common.css"
  • file-loader、raw-loader、url-loader ```javascript // 安装 yarn add file-laoder

// webpack.config.js使用 module.exports = { module: { // 模块配置相关(配置 loader、解析器等选项) rules: [ { test: /.(png|jpe?g|gif)$/i, use: [ { loader: ‘file-loader’ } ] } ] } }

// 使用 import icon from “./assets/icon02.png”

  1. - **babel-loader** ( 将高级语法转义成低版本浏览器也能认识的插件)
  2. ```javascript
  3. // 安装
  4. babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime -D
  5. // webpack.config.js使用
  6. module.exports = {
  7. module: {
  8. // 模块配置相关(配置 loader、解析器等选项)
  9. rules: [
  10. {
  11. test: /\.m?js$/,
  12. exclude: /(node_modules|bower_components)/,
  13. use: {
  14. loader: 'babel-loader',
  15. options: {
  16. presets: ['@babel/preset-env'],
  17. plugins: ['@babel/plugin-transform-runtime']
  18. }
  19. }
  20. }
  21. ]
  22. }
  23. }
  24. // 使用
  25. // test1.js
  26. export const fn = async () =>{
  27. const res = await asyncTest()
  28. console.log('function',res)
  29. }
  30. function asyncTest(){
  31. return new Promise( resolve =>{
  32. setTimeout( () =>{
  33. resolve(1111)
  34. },2000)
  35. })
  36. }
  37. // main.js
  38. import { fn } from "./test1.js"
  39. const mains = "main.js"
  40. console.log(test1)
  41. fn()

plugin
  • UglifyJsPlugin 压缩和混淆代码 ```javascript // 安装 yarn add uglifyjs-webpack-plugin -D

// webpack.config.js使用 const UglifyJsPlugin = require(‘uglifyjs-webpack-plugin’); module.exports = { optimization: { minimizer: [ new UglifyJsPlugin({ cache: true, parallel: true }) ] } }

  1. - **html-webpack-plugin **自动生成html、并引用打包后的js
  2. ```javascript
  3. // 安装
  4. yarn add html-webpack-plugin -D
  5. // webpack.config.js使用
  6. const HtmlWebpackPlugin = require('html-webpack-plugin')
  7. module.exports = {
  8. plugins: [
  9. new HtmlWebpackPlugin()
  10. ]
  11. }
  • webpack-bundle-analyzer 打包分析插件、可以分析你的打包内容所消耗的时间、根据各种维度去分析进行优化打包速度 ```javascript // 安装 yarn add webpack-bundle-analyzer -D

// webpack.config.js使用 const BundleAnalyzerPlugin = require(‘webpack-bundle-analyzer’).BundleAnalyzerPlugin; module.exports = { plugins: [ new BundleAnalyzerPlugin() ] }

// 执行build后会自动打开分析的html文件

  1. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/12473205/1648884029632-3b69620d-249f-4ed4-8c8a-0482c5ea5c23.png#clientId=u5018bb80-69ba-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=886&id=u4c10a72a&margin=%5Bobject%20Object%5D&name=image.png&originHeight=975&originWidth=1920&originalType=binary&ratio=1&rotation=0&showTitle=false&size=890161&status=done&style=shadow&taskId=uf6f91c96-4cf0-483b-9a87-fc5eca8b969&title=&width=1745.4545076228378)
  2. - **optimize-css-assets-webpack-plugin** 不同组件中重复的css可以快速去重
  3. - **happypack** 通过多进程模型,来加速代码构建
  4. <a name="dkGrk"></a>
  5. ### 贴上整体基础配置文件
  6. ```javascript
  7. const path = require('path');
  8. const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
  9. const HtmlWebpackPlugin = require('html-webpack-plugin')
  10. const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
  11. module.exports = {
  12. // 入口文件
  13. entry: {
  14. 'main': './src/main.js',
  15. },
  16. // 此选项控制是否生成,以及如何生成 source map。
  17. devtool: 'inline-source-map',
  18. // 模式-环境
  19. mode: 'development',
  20. module: {
  21. // 模块配置相关(配置 loader、解析器等选项)
  22. rules: [
  23. {
  24. test: /\.css$/i,
  25. use: ["style-loader", "css-loader"],
  26. },
  27. {
  28. test: /\.(png|jpe?g|gif)$/i,
  29. use: [
  30. {
  31. loader: 'file-loader',
  32. }
  33. ]
  34. },
  35. {
  36. test: /\.m?js$/,
  37. exclude: /(node_modules|bower_components)/,
  38. use: {
  39. loader: 'babel-loader',
  40. options: {
  41. presets: ['@babel/preset-env'],
  42. plugins: ['@babel/plugin-transform-runtime']
  43. }
  44. }
  45. }
  46. ]
  47. },
  48. optimization: {
  49. minimizer: [
  50. new UglifyJsPlugin({
  51. cache: true,
  52. parallel: true
  53. })
  54. ],
  55. splitChunks: {
  56. // 抽离入口文件公共模块为commmons模块
  57. cacheGroups: {
  58. commons: {
  59. name: "commons",
  60. chunks: "initial",
  61. minChunks: 2
  62. }
  63. }
  64. }
  65. },
  66. // 插件使用
  67. plugins: [
  68. new HtmlWebpackPlugin(),
  69. new BundleAnalyzerPlugin()
  70. ],
  71. // 输出规则
  72. output: {
  73. // 输出的文件名、[name] 来自打包的名称
  74. filename: '[name].bundle.js',
  75. // 输出的位置
  76. path: path.resolve(__dirname, 'dist'),
  77. // 在生成文件之前清空 output 目录
  78. clean: true
  79. }
  80. };

webpack构建流程

我们在学习了webpack基础打包配置后、现在我们还需要学习下webpack构建的整个流程是什么样的、了解其基本的构建过程有助于我们更熟悉webpack、今后使用webpack更能知道那个环节可以优化和排查问题! 下面贴一张网上找的图片、个人觉得写的很清晰!可以先看图了解下整个过程!

TB1GVGFNXXXXXaTapXXXXXXXXXX-4436-4244.jpg

一、合并参数

启动打包后、webpack会把默认配置和用户自定义的配置( webpack.config.js ) 进行参数配置合并、得到最终的options对象给到下一个流程!!

二、实例化Compiler和订阅生命周期

合并完配置对象后、准备初始化compiler对象、该对象是继承至Tapabel、给所有的插件注册生命周期的订阅、然后执行run方法开始执行编译!

三、parser分析项目依赖

找到入口文件、开始分析文件构建AST树、找出依赖递归下去处理、依赖递归根据文件类型去命中相对应的loader配置、调用配置中的所有loader对文件进行transformation

四、输出文件

递归完所有的依赖后、就能拿到每个文件结果、根据entry的配置或者分包配置生成对应的chunk文件

本篇package.json版本

  1. {
  2. "name": "webpack-cli-test",
  3. "version": "1.0.0",
  4. "main": "index.js",
  5. "license": "MIT",
  6. "scripts": {
  7. "build": "webpack --config webpack.config.js"
  8. },
  9. "devDependencies": {
  10. "@babel/core": "^7.17.8",
  11. "@babel/plugin-transform-runtime": "^7.17.0",
  12. "@babel/preset-env": "^7.16.11",
  13. "babel-loader": "^8.2.4",
  14. "css-loader": "^6.7.1",
  15. "file-loader": "^6.2.0",
  16. "html-webpack-plugin": "^5.5.0",
  17. "style-loader": "^3.3.1",
  18. "uglifyjs-webpack-plugin": "^2.2.0",
  19. "webpack": "^5.71.0",
  20. "webpack-bundle-analyzer": "^4.5.0",
  21. "webpack-cli": "^4.9.2"
  22. }
  23. }