webpack

⼀、webpack 简介

1.1 webpack 是什么

webpack 是⼀种前端资源构建⼯具,⼀个静态模块打包器(module bundler)。
webpack 看来, 前端的所有资源⽂件(js/json/css/img/less/…)都会作为模块处理。
它将根据模块的依赖关系进⾏静态分析,打包⽣成对应的静态资源(bundle)。
官⽹:https://webpack.js.org/

  • 前端资源构建⼯具:主要理解⼀下这个前端资源是哪些资源。这些前端资源就是浏览器不认识的 web 资源, ⽐如sasslessts,包括 js ⾥的⾼级语法。这些资源要能够在浏览器中正常⼯作,必须⼀⼀经过编译处理。⽽ webpack 就是可以集成这些编译⼯具的⼀个总的构建⼯具。
  • 静态模块打包器:静态模块就是 web 开发过程中的各种资源⽂件,webpack 根据引⽤关系,构建⼀个依赖关系图,然后利⽤这个关系图将所有静态模块打包成⼀个或多个 bundle 输出。
1.2 为什么我们需要 webpack
  • web 开发时调⽤后端接⼝跨域,需要其他⼯具代理或者其他⽅式规避。
  • 改动代码后要⼿动刷新浏览器,如果做了缓存还需要清缓存刷新。
  • 因为 jscss 的兼容性问题,很多新语法学习了却不能使⽤,⽆论是开发效率和个⼈成⻓都受影响。
  • 打包问题。需要使⽤额外的平台如 jekins 打包,⾃⼰编写打包脚本,对各个环节如压缩图⽚,打包 js、打包 css 都要⼀⼀处理。
1.3 webpack 五个核⼼概念
1.3.1 Entry

⼊⼝(Entry)指示 webpack 以哪个⽂件为⼊⼝起点开始打包,分析构建内部依赖图。

// string⽅式: 单⼊⼝,打包形成⼀个trunk,输出⼀个buldle⽂件。trunk的名称默认是main.js
entry: "./src/index.js"
// array⽅式:多⼊⼝,所有⼊⼝⽂件最终只会形成⼀个trunk,输出出去只有⼀个bundle⽂件
entry: ["./src/index.js", "./src/test.js"]
// object:多⼊⼝,有⼏个⼊⼝⽂件就形成⼏个trunk,输出⼏个bundle⽂件。此时trunk的名称就是对象key值 
entry: {
  index: "./src/index.js",
  test: "./src/test.js", 
}
//当构建项⽬包含多个⼦项⽬时,每次增加⼀个⼦系统都需要将⼊⼝⽂件写⼊webpack配置⽂件中,其实我们让webpack动态获取⼊⼝⽂件,
// 使⽤ glob 等⼯具使⽤若⼲通配符,运⾏时获得 entry 的条⽬
entry: glob.sync('./project/**/index.js').reduce((acc, path) => {
  const entry = path.replace('/index.js', '')
  acc[entry] = path
  return acc
}, {})
//则会将所有匹配`./project/**/index.js`的⽂件作为⼊⼝⽂件进⾏打包,如果你想要增加⼀个⼦项⽬,仅仅需要在`project`创建⼀个⼦项⽬⽬录,并创建⼀个`index.js` 作为⼊⼝⽂件即可。
//这种⽅式⽐较适合⼊⼝⽂件不集中且较多的场景。
1.3.2 Output

输出(Output)指示 webpack打包后的资源 bundles 输出到哪⾥去,以及如何命名。

 output: { 
   // 输出⽂件⽬录(将来所有资源输出的公共⽬录,包括css和静态⽂件等等)
   path: path.resolve(__dirname, "dist"), //默认
   // ⽂件名称(指定名称+⽬录)
   filename: "[name].js", // 默认
   // 或使⽤函数返回名(不常⽤) 
   // filename: (chunkData) => {
   // return chunkData.chunk.name === 'main' ? '[name].js': '[name]/[name].js'; 
   // },
   // 所有资源引⼊公共路径前缀,⼀般⽤于⽣产环境,⼩⼼使⽤
   // 打包⽣成的 index.html ⽂件⾥⾯引⽤资源的前缀
   // 也为发布到线上资源的 URL 前缀
   // 使⽤的是相对路径,默认为 ''
   publicPath: "",
   /* 
   ⾮⼊⼝⽂件chunk的名称。所谓⾮⼊⼝即import动态导⼊形成的trunk或者optimization中的splitChunks提取的公共trunk
   它⽀持和 filename ⼀致的内置变量
   */
   chunkFilename: "[contenthash:10].chunk.js",

   /* 当⽤ Webpack 去构建⼀个可以被其他模块导⼊使⽤的库时需要⽤到library */
   library: {
     name: "[name]",//整个库向外暴露的变量名
     type: "window"//库暴露的⽅式
   }
},
1.3.3 Loader

Loaderwebpack能够去处理那些⾮JavaScript⽂件 (webpack⾃身只理解JavaScript)

  rules: [
    {
      // 匹配哪些⽂件
      test: /\.css$/,
      // 使⽤哪些loader进⾏处理。执⾏顺序,从右⾄左,从下⾄上
      use: [
        // 创建style标签,将js中的样式资源(就是css-loader转化成的字符串)拿过来,添加到⻚⾯head标签⽣效
        "style-loader",
        // 将css⽂件变成commonjs⼀个模块加载到js中,⾥⾯的内容是样式字符串
        "css-loader",
        {
          // css 兼容处理 postcss,注意需要在package.json配置browserslist
          loader: "postcss-loader",
          options: {
            postcssOptions: {
              ident: "postcss",
              // postcss-preset-env插件:帮postcss找到package.json中的browserslist配置,根据配置加载指定的兼容性样式 
              plugins: [require("postcss-preset-env")()],
            },
          },
        }],
    },
    {
      test: /\.js$/,
      // 注意需要在package.json配置browserslist,否则babel-loader不⽣效
      // js兼容处理 babel
      loader: "babel-loader", // 规则只使⽤⼀个loader时推荐写法
      options: {
        presets: [
          [
            "@babel/preset-env",// 预设:指示babel做怎么样的兼容处理
            {
              useBuiltIns: "usage", //按需加载
              corejs: {
                version: "3",
              },
              targets: "defaults",
            }
          ]
        ]
      }
    },
    /**
    * Webpack5.0新增资源模块(asset module),它是⼀种模块类型,允许使⽤资源⽂件(字体,图标等)⽽⽆需配置额外loader。⽀持以下四个配置
    * asset/resource 发送⼀个单独的⽂件并导出 URL。之前通过使⽤ file-loader 实现。
    * asset/inline 导出⼀个资源的 data URI。之前通过使⽤ url-loader 实现。
    * asset/source 导出资源的源代码。之前通过使⽤ raw-loader 实现。
    * asset 在导出⼀个 data URI 和发送⼀个单独的⽂件之间⾃动选择。之前通过使⽤ url-loader,并且配置资源体积限制实现。
    **/
    // Webpack4使⽤file-loader实现
    {
      test: /\.(eot|svg|ttf|woff|)$/,
      type: "asset/resource",
      generator: {
        // 输出⽂件位置以及⽂件名
        filename: "fonts/[name][ext]"
      },
    },
    // Webpack4使⽤url-loader实现
    {
      //处理图⽚资源
      test: /\.(jpg|png|gif|)$/,
      type: "asset",
      generator: {
        // 输出⽂件位置以及⽂件名
        filename: "images/[name][ext]"
      },
      parser: {
        dataUrlCondition: {
          maxSize: 10 * 1024 //超过10kb不转base64
        }
      }
    },
  ]
1.3.4 Plugins

插件(Plugins)可以⽤于执⾏范围更⼴的任务。插件的范围包括,从打包优化和压缩,⼀直到重新定义环境中的变量等。
它并不会影响 Webpack 的核⼼⼯作过程,只是 Webpack 为了提供⼀个强⼤的扩展能⼒,它为整个⼯作过程的每个环节都预制了⼀个钩⼦,也就是说我们可以通过插件往 Webpack ⼯作过程的任意环节植⼊⼀些⾃定义的任务,从⽽扩展 Webpack打包功能以外的能⼒。

// CleanWebpackPlugin帮助你在打包时⾃动清除dist⽂件,学习时使⽤⽐较⽅便
const { CleanWebpackPlugin } = require("clean-webpack-plugin"); 

// HtmlWebpackPlugin帮助你创建html⽂件,并⾃动引⼊打包输出的bundles⽂件。⽀持html压缩。
const HtmlWebpackPlugin = require("html-webpack-plugin"); 

// 该插件将CSS提取到单独的⽂件中。它会为每个trunk创造⼀个css⽂件。需配合loader⼀起使⽤
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); 

// 该插件将在Webpack构建过程中搜索CSS资源,并优化\最⼩化CSS
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");

// vue-loader V15版本以上,需要引⼊VueLoaderPlugin插件,它的作⽤是将你定义过的js、css等规则应⽤到vue⽂件中去。
const { VueLoaderPlugin } = require('vue-loader')

module.exports = {
  module: {
    rules: [{
      test: /\.vue$/,
      loader: "vue-loader"
    },
    {
      test: /\.css$/,
      use: [
        // MiniCssExtractPlugin.loader的作⽤就是把css-loader处理好的样式资源(js⽂件内),单独提取出来 成为css样式⽂件
       MiniCssExtractPlugin.loader,//⽣产环境下使⽤,开发环境还是推荐使⽤style-loader
       "css-loader",
      ],
    }],
  },
  plugins: [
    new CleanWebpackPlugin(),
    new HtmlWebpackPlugin({
      template:"index.html"
    }),
    new MiniCssExtractPlugin({
      filename: "css/built.css",
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new VueLoaderPlugin(),
  ]
}

插件都是通过往 Webpack ⽣命周期的钩⼦中挂载任务函数实现的。

class RemoveCommentsPlugin {
  apply(compiler) {
    compiler.hooks.emit.tap('RemoveCommentsPlugin', compilation => {
      // compilation => 可以理解为此次打包的上下⽂
      for (const name in compilation.assets) {
        if (name.endsWith('.js')) {
          const contents = compilation.assets[name].source()
          const noComments = contents.replace(/\/\*{2,}\/\s?/g, '')
          compilation.assets[name] = {
            source: () => noComments,
            size: () => noComments.length
          }
        }
      }
    })
  }
}
1.3.5 Mode

模式(Mode)指示 webpack 使⽤相应模式的配置。

选项描述特点
development会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。启⽤ NamedChunksPlugin 和 NamedModulesPlugin。能让代码本地调试,运⾏的环境
production会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。启⽤FlagDependencyUsagePlugin,FlagIncludedChunksPlugin,ModuleConcatenationPlugin,NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 TerserPlugin。能让代码优化上线运⾏的环境

⼆、webpack 的使⽤

Webpack 在整个打包的过程中:

通过 Loader 处理特殊类型资源的加载,例如加载样式、图⽚;
通过 Plugin 实现各种⾃动化的构建任务,例如⾃动压缩、⾃动发布。

  1. Webpack CLI 启动打包流程;
  2. 载⼊ Webpack 核⼼模块,创建 Compiler 对象;
  3. 使⽤ Compiler 对象开始编译整个项⽬;
  4. 从⼊⼝⽂件开始,解析模块依赖,形成依赖关系树;
  5. 递归依赖树,将每个模块交给对应的 Loader 处理;
  6. 合并 Loader 处理完的结果,将打包结果输出到 dist ⽬录。

先安装 webpack 相关的 npm 包,然后使⽤ webpack-cli 所提供的命令⾏⼯具进⾏打包。

2.1 初始化配置
2.1.1 初始化 package.json

npm init

2.1.2 下载并安装 webpack

npm install webpack webpack-cli -g
npm install webpack webpack-cli -D

2.2 编译打包应⽤
2.2.1 创建⽂件

选项 描述 特点
development 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。
启⽤ NamedChunksPlugin 和 NamedModulesPlugin。
能让代码本地调试
运⾏的环境
production
会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。
启⽤FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin,
NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 TerserPlugin。
能让代码优化上线运⾏的环境

2.2.2 运⾏指令

开发环境指令:webpack src/index.js -o build/built.js --mode=development
功能:webpack 能够编译打包 jsjson ⽂件,并且能将 es6 的模块化语法转换成浏览器能识别的语法。
⽣产环境指令:webpack src/index.js -o build/built.js --mode=production
功能:在开发配置功能上多⼀个功能,压缩代码。

2.2.3 结论
  • webpack 能够编译打包 jsjson ⽂件。
  • 能将 es6 的模块化语法转换成浏览器能识别的语法。
  • 能压缩代码。
2.2.4 问题
  • 不能编译打包 cssimg等⽂件。
  • 不能将 jses6 基本语法转化为 es5 以下语法。

三、webpack 开发、⽣产配置

开发环境配置
/*
  开发环境配置:能让代码运行
    运行项目指令:
      webpack 会将打包结果输出出去
      npx webpack-dev-server 只会在内存中编译打包,没有输出
*/

const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // entry: './src/js/index.js',
  entry: resolve(__dirname, './src/js/index.js') ,
  //entry: ['./src/js/index.js', './src/index.html'], HMR开启
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // loader的配置
      {
        // 处理less资源
        // 匹配哪些文件
        test: /\.less$/, // 匹配哪些文件
        // use数组中loader执行顺序:从右到左,从下到上 依次执行
        // style-loader:创建style标签,将js中的样式资源插入进行,添加到head中生效
        // css-loader:将css文件变成commonjs模块加载js中,里面内容是样式字符串
        // less-loader:将less文件编译成css文件 需要下载 less-loader和less
        use: ['style-loader', 'css-loader', 'less-loader']
      },
      {
        // 处理css资源
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        // 处理图片资源
        // 问题:默认处理不了html中img图片
        // 处理图片资源
        test: /\.(jpg|png|gif)$/,
        // 使用一个loader
        // 下载 url-loader file-loader
        loader: 'url-loader',
        options: {
          // 图片大小小于8kb,就会被base64处理
          // 优点: 减少请求数量(减轻服务器压力)
          // 缺点:图片体积会更大(文件请求速度更慢)
          limit: 8 * 1024,
          // 给图片进行重命名
          // [hash:10]取图片的hash的前10位
          // [ext]取文件原来扩展名
          name: '[hash:10].[ext]',
          // 关闭es6模块化
          // 问题:因为url-loader默认使用es6模块化解析,而html-loader引入图片是commonjs
          // 解析时会出问题:[object Module]
          // 解决:关闭url-loader的es6模块化,使用commonjs解析
          esModule: false,
          outputPath: 'imgs'
        }
      },
      {
        // 处理html中img资源
        // 处理html文件的img图片(负责引入img,从而能被url-loader进行处理)
        test: /\.html$/,
        loader: 'html-loader'
      },
      // 打包其他资源(除了html/js/css资源以外的资源)
      {
        // 处理其他资源
        exclude: /\.(html|js|css|less|jpg|png|gif)/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'font'
        }
      }
    ]
  },
  plugins: [
    // plugins的配置
    // html-webpack-plugin
    // 功能:默认会创建一个空的HTML,自动引入打包输出的所有资源(JS/CSS)
    // 需求:需要有结构的HTML文件
    new HtmlWebpackPlugin({
      // 复制 './src/index.html' 文件,并自动引入打包输出的所有资源(JS/CSS)
      template: './src/index.html'
    })
  ],
  mode: 'development',
  // 开发服务器 devServer:用来自动化(自动编译,自动打开浏览器,自动刷新浏览器~~)
  // 特点:只会在内存中编译打包,不会有任何输出
  // 启动devServer指令为:npx webpack-dev-server
  devServer: {
    // 运行代码的目录
    contentBase: resolve(__dirname, 'build'),
    // 监视 contentBase 目录下的所有文件,一旦文件变化就会 reload
    watchContentBase: true,
    watchOptions: {
      // 忽略文件
      ignored: /node_modules/
    },
    // 启动gzip压缩
    compress: true,
    // 端口号
    port: 5000,
    // 域名
    host: 'localhost',
    // 自动打开浏览器
    open: true,
    // 开启HMR功能
    /*
    HMR: hot module replacement 热模块替换 / 模块热替换
    作用:一个模块发生变化,只会重新打包这一个模块(而不是打包所有模块) 
      极大提升构建速度
    样式文件:可以使用HMR功能:因为style-loader内部实现了~
    js文件:默认不能使用HMR功能 --> 需要修改js代码,添加支持HMR功能的代码
        注意:HMR功能对js的处理,只能处理非入口js文件的其他文件。
    html文件: 默认不能使用HMR功能.同时会导致问题:html文件不能热更新了~ (不用做HMR功能)
        解决:修改entry入口,将html文件引入
    */
    // 当修改了webpack配置,新配置要想生效,必须重新webpack服务
    hot: true,
    // 不要显示启动服务器日志信息
    clientLogLevel: 'none',
    // 除了一些基本启动信息以外,其他内容都不要显示
    quiet: true,
    // 如果出错了,不要全屏提示~
    overlay: false,
    // 服务器代理 --> 解决开发环境跨域问题
    proxy: {
      // 一旦devServer(5000)服务器接受到 /api/xxx 的请求,就会把请求转发到另外一个服务器(3000)
      '/api': {
        target: 'http://localhost:3000',
        // 发送请求时,请求路径重写:将 /api/xxx --> /xxx (去掉/api)
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  },
  devtool: 'eval-source-map',
  resolve: {
    // 配置解析模块路径别名: 优点简写路径 缺点路径没有提示
    alias: {
      $css: resolve(__dirname, 'src/css')
    },
    // 配置省略文件路径的后缀名
    extensions: ['.js', '.json', '.jsx', '.css'],
    // 告诉 webpack 解析模块是去找哪个目录
    modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
  }
};

生产环境配置
const { resolve } = require("path");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

// 定义nodejs环境变量:决定使用browserslist的哪个环境
process.env.NODE_ENV = "production";

// 复用loader
const commonCssLoader = [
  // 创建style标签,将样式放入
  // 'style-loader',
  // 这个loader取代style-loader。作用:提取js中的css成单独文件
  MiniCssExtractPlugin.loader,
  "css-loader",
  {
    // 还需要在package.json中定义browserslist
    /*
    css兼容性处理:postcss --> postcss-loader postcss-preset-env
    帮postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式
    "browserslist": {
      // 开发环境 --> 设置node环境变量:process.env.NODE_ENV = development
      "development": [
         "last 1 chrome version",
         "last 1 firefox version",
          "last 1 safari version"
      ],
      // 生产环境:默认是看生产环境
      "production": [
         ">0.2%",
         "not dead",
          "not op_mini all"
      ]
    }
    */
    // 使用loader的默认配置
    // 'postcss-loader',
    // 修改loader的配置
    loader: "postcss-loader",
    options: {
      ident: "postcss",
      plugins: () => [require("postcss-preset-env")()],
    },
  },
];

module.exports = {
  entry: "./src/js/index.js",
  output: {
    filename: "js/built.js",
    path: resolve(__dirname, "build"),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [...commonCssLoader],
      },
      {
        test: /\.less$/,
        use: [...commonCssLoader, "less-loader"],
      },
      /*
        正常来讲,一个文件只能被一个loader处理。
        当一个文件要被多个loader处理,那么一定要指定loader执行的先后顺序:
          先执行eslint 在执行babel
      */
      {
        // 在package.json中eslintConfig --> airbnb
        test: /\.js$/,
        exclude: /node_modules/,
        // 优先执行
        enforce: "pre",
        loader: "eslint-loader",
        options: {
          // 自动修复eslint的错误
          fix: true,
        },
      },
      /*
        js兼容性处理:babel-loader @babel/core 
          1. 基本js兼容性处理 --> @babel/preset-env
            问题:只能转换基本语法,如promise高级语法不能转换
          2. 全部js兼容性处理 --> @babel/polyfill  
            问题:我只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了~
          3. 需要做兼容性处理的就做:按需加载  --> core-js
      */
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: "babel-loader",
        options: {
          // 预设:指示babel做怎么样的兼容性处理
          presets: [
            [
              "@babel/preset-env",
              {
                // 按需加载
                useBuiltIns: "usage",
                // 指定core-js版本
                corejs: { version: 3 },
                // 指定兼容性做到哪个版本浏览器
                targets: {
                  chrome: "60",
                  firefox: "50",
                  ie: "9",
                  safari: "10",
                  edge: "17"
                },
              },
            ],
          ],
          cacheDirectory: true //bable 缓存
        },
      },
      {
        test: /\.(jpg|png|gif)/,
        loader: "url-loader",
        options: {
          limit: 8 * 1024,
          name: "[hash:10].[ext]",
          outputPath: "imgs",
          esModule: false,
        },
      },
      {
        test: /\.html$/,
        loader: "html-loader",
      },
      {
        exclude: /\.(js|css|less|html|jpg|png|gif)/,
        loader: "file-loader",
        options: {
          outputPath: "font",
        },
      },
    ],
  },
  plugins: [
    // 对输出的css文件进行重命名
    new MiniCssExtractPlugin({
      filename: "css/built.css",
    }),
    // 压缩css
    new OptimizeCssAssetsWebpackPlugin(),
    // 压缩html代码
    new HtmlWebpackPlugin({
      template: "./src/index.html",
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注释
        removeComments: true,
      },
    }),
  ],
  // 生产环境下会自动压缩js代码
  mode: "production",
  externals: {
    // 拒绝jQuery被打包进来
    jquery: 'jQuery'
  }
};

四、webpack 性能优化

4.1 开发环境性能优化
  • 优化打包构建速度
    • HMR
  • 优化代码调试
    • source-map : ⼀种 提供源代码到构建后代码映射 技术 (如果构建后代码出错了,通过映射可以追踪源代码错误)[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
      • a.source-map:外部
        产⽣⼀个单独的source-map⽂件,功能最完全,但会减慢打包速度
      • b. inline-source-map:内联
        只⽣成⼀个内联source-map
        错误代码准确信息 和 源代码的错误位置
      • c. hidden-source-map:外部
        错误代码错误原因,但是没有错误位置
        不能追踪源代码错误,只能提示到构建后代码的错误位置
      • d.eval-source-map:内联
        使⽤eval打包源⽂件模块,直接在源⽂件中写⼊⼲净完整的source-map,不影响构建速度,但影响执⾏速度和安
        全,建议开发环境中使⽤,⽣产阶段不要使⽤
      • e.nosources-source-map:外部
        错误代码准确信息, 但是没有任何源代码信息
      • f.cheap-source-map:外部
        错误代码准确信息 和 源代码的错误位置,只能精确的⾏
      • g.cheap-module-source-map:外部
        错误代码准确信息 和 源代码的错误位置
        module会将loader的source map加⼊

内联 和 外部的区别:1. 外部⽣成了⽂件,内联没有 2. 内联构建速度更快

开发环境推荐使⽤:

  • 1.eval :每个模块使⽤eval()和//@ sourceURL执⾏。这是⾮常快。主要缺点是,它没有正确显示⾏号,因为它被映射到转换代码⽽不是原始代码(没有来⾃加载器的源映射)。
  • 2.eval-source-map:每个模块使⽤eval()执⾏,⽽SourceMap作为DataUrl添加到eval()中。最初它是缓慢的,但是
    它提供快速的重建速度和产⽣真实的⽂件。⾏号被正确映射,因为它被映射到原始代码。它产⽣了最优质的开发资源。
  • 3.cheap-eval-source-map:与eval-source-map类似,每个模块都使⽤eval()执⾏。它没有列映射,它只映射⾏
    号。它忽略了来⾃加载器的源代码,并且只显示与eval devtool相似的经过转换的代码。
  • 4.cheap-module-eval-source-map:类似于cheap-eval-source-map,在本例中,来⾃加载器的源映射被处理以获
    得更好的结果。然⽽,加载器源映射被简化为每⼀⾏的单个映射。

⽣产环境推荐使⽤:

  • 1.(none) :(省略devtool选项)-不触发SourceMap。这是⼀个很好的选择。
  • 2.source-map:⼀个完整的SourceMap是作为⼀个单独的⽂件。它为bundle 添加了引⽤注释,因此开发⼯具知道在哪⾥找到它。
  • 3.hidden-source-map:与source-map相同,但不向bundle 添加引⽤注释。如果您只希望SourceMaps从错误报告
    中映射错误堆栈跟踪,但不想为浏览器开发⼯具暴露您的SourceMap,可以使⽤此选项。
  • 4.nosources-source-map:⼀个SourceMap是在没有源代码的情况下创建的。它可以⽤于在客户机上映射堆栈跟
    踪,⽽不暴露所有源代码。您可以将源映射⽂件部署到webserver。

webpack devtool: https://webpack.docschina.org/configuration/devtool/

4.2 ⽣产环境性能优化
  • 优化打包构建速度
    • oneOf --每个不同类型的⽂件在 loader 转换时,都会被命中,遍历 module 中 rules 中所有 loader.
      • 使⽤ oneOf 根据⽂件类型加载对应的 loader,只要能匹配⼀个即可退出,
      • 对于同⼀类型⽂件,⽐如处理 js,如果需要多个 loader,可以单独抽离 js 处理,确保 oneOf ⾥⾯⼀个⽂件类型对应⼀个 loader
      • 可以配置 enforce: ‘pre’,指定优先执⾏
    • babel 缓存: cacheDirectory: true --> 让第⼆次打包构建速度更快
      • hash: 每次 wepack 构建时会⽣成⼀个唯⼀的 hash 值。
        问题: 因为 js 和 css 同时使⽤⼀个 hash 值。–> 如果重新打包,会导致所有缓存失效。(可能我却只改动⼀个⽂件)
      • chunkhash:根据 chunk ⽣成的 hash 值。如果打包来源于同⼀个 chunk,那么 hash 值就⼀样
        问题: js 和 css 的 hash 值还是⼀样的–> 因为 css 是在 js 中被引⼊的,所以同属于⼀个 chunk
      • contenthash: 根据⽂件的内容⽣成 hash 值。不同⽂件 hash 值⼀定不⼀样–> 让代码上线运⾏缓存更好使⽤
    • 多进程打包
    • externals
    • dll
  • 优化代码运⾏的性能
    • 缓存(hash-chunkhash-contenthash)
    • tree shaking
    • code split
    • 懒加载/预加载
    • pwa
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值