webpack 入門

一、Webpack 簡(jiǎn)介

1.1 webpack 是什么

webpack 是一種前端資源構(gòu)建工具粹断,一個(gè)靜態(tài)模塊打包器(module bundler)稿湿。

在webpack 看來(lái), 前端的所有資源文件(js/json/css/img/less/...)都會(huì)作為模塊處理。
它將根據(jù)模塊的依賴關(guān)系進(jìn)行靜態(tài)分析族铆,打包生成對(duì)應(yīng)的靜態(tài)資源(bundle)将硝。

1.2 webpack 五個(gè)核心概念

1.2.1 Entry

入口(Entry):指示 webpack 以哪個(gè)文件為入口起點(diǎn)開始打包一屋,分析構(gòu)建內(nèi)部依賴圖。

1.2.2 Output

輸出(Output):指示 webpack 打包后的資源 bundles 輸出到哪里去袋哼,以及如何命名。

1.2.3 Loader

Loader:讓 webpack 能夠去處理那些非 JS 的文件闸衫,比如樣式文件涛贯、圖片文件(webpack 自身只理解
JS)

1.2.4 Plugins

插件(Plugins):可以用于執(zhí)行范圍更廣的任務(wù)。插件的范圍包括蔚出,從打包優(yōu)化和壓縮弟翘,
一直到重新定義環(huán)境中的變量等。

1.2.5 Mode

模式(Mode):指示 webpack 使用相應(yīng)模式的配置骄酗。

表頭 表頭 特點(diǎn)
development 會(huì)將 DefinePlugin 中 process.env.NODE_ENV 的值設(shè)置為 development稀余。 能讓代碼本地調(diào)試運(yùn)行的環(huán)境
production 會(huì)將 DefinePlugin 中 process.env.NODE_ENV 的值設(shè)置為 production。啟用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 TerserPlugin趋翻。 能讓代碼優(yōu)化上線運(yùn)行的環(huán)境

二睛琳、Webpack 初體驗(yàn)

2.1 初始化配置

  1. 初始化 package.json:npm init

  2. 下載安裝webpack:(webpack4以上的版本需要全局/本地都安裝webpack-cli)

    全局安裝:cnpm i webpack webpack-cli -g

    本地安裝:cnpm i webpack webpack-cli -D

2.2 編譯打包應(yīng)用

創(chuàng)建 src 下的 js 等文件后,不需要配置 webpack.config.js 文件,在命令行就可以編譯打包师骗。

指令:

  • 開發(fā)環(huán)境:webpack ./src/index.js -o ./build/built.js --mode=development

    webpack會(huì)以 ./src/index.js 為入口文件開始打包历等,打包后輸出到 ./build/built.js 整體打包環(huán)境,是開發(fā)環(huán)境

  • 生產(chǎn)環(huán)境:webpack ./src/index.js -o ./build/built.js --mode=production

    webpack會(huì)以 ./src/index.js 為入口文件開始打包辟癌,打包后輸出到 ./build/built.js 整體打包環(huán)境寒屯,是生產(chǎn)環(huán)境

結(jié)論:

  1. webpack 本身能處理 js/json 資源,不能處理 css/img 等其他資源

  2. 生產(chǎn)環(huán)境和開發(fā)環(huán)境將 ES6 模塊化編譯成瀏覽器能識(shí)別的模塊化黍少,但是不能處理 ES6 的基本語(yǔ)法轉(zhuǎn)化為 ES5(需要借助 loader)

  3. 生產(chǎn)環(huán)境比開發(fā)環(huán)境多一個(gè)壓縮 js 代碼

三寡夹、Webpack 開發(fā)環(huán)境的基本配置

webpack.config.js 是 webpack 的配置文件。

作用: 指示 webpack 干哪些活(當(dāng)你運(yùn)行 webpack 指令時(shí)厂置,會(huì)加載里面的配置)

所有構(gòu)建工具都是基于 nodejs 平臺(tái)運(yùn)行的菩掏,模塊化默認(rèn)采用 commonjs。

開發(fā)環(huán)境配置主要是為了能讓代碼運(yùn)行农渊。主要考慮以下幾個(gè)方面:

  • 打包樣式資源
  • 打包 html 資源
  • 打包圖片資源
  • 打包其他資源
  • devServer

下面是一個(gè)簡(jiǎn)單的開發(fā)環(huán)境webpack.confg.js配置文件

// resolve用來(lái)拼接絕對(duì)路徑的方法
const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin') // 引用plugin

module.exports = {
  // webpack配置
  entry: './src/js/index.js', // 入口起點(diǎn)
  output: {
    // 輸出
    // 輸出文件名
    filename: 'js/build.js',
    // __dirname是nodejs的變量患蹂,代表當(dāng)前文件的目錄絕對(duì)路徑
    path: resolve(__dirname, 'build'), // 輸出路徑,所有資源打包都會(huì)輸出到這個(gè)文件夾下
  },
  // loader配置
  module: {
    rules: [
      // 詳細(xì)的loader配置
      // 不同文件必須配置不同loader處理
      {
        // 匹配哪些文件
        test: /\.less$/,
        // 使用哪些loader進(jìn)行處理
        use: [
          // use數(shù)組中l(wèi)oader執(zhí)行順序:從右到左砸紊,從下到上传于,依次執(zhí)行(先執(zhí)行css-loader)
          // style-loader:創(chuàng)建style標(biāo)簽,將js中的樣式資源插入進(jìn)去醉顽,添加到head中生效
          'style-loader',
          // css-loader:將css文件變成commonjs模塊加載到j(luò)s中沼溜,里面內(nèi)容是樣式字符串
          'css-loader',
          // less-loader:將less文件編譯成css文件,需要下載less-loader和less
          'less-loader'
        ],
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        // url-loader:處理圖片資源游添,問(wèn)題:默認(rèn)處理不了html中的img圖片
        test: /\.(jpg|png|gif)$/,
        // 需要下載 url-loader file-loader
        loader: 'url-loader',
        options: {
          // 圖片大小小于8kb系草,就會(huì)被base64處理,優(yōu)點(diǎn):減少請(qǐng)求數(shù)量(減輕服務(wù)器壓力)唆涝,缺點(diǎn):圖片體積會(huì)更大(文件請(qǐng)求速度更慢)
          // base64在客戶端本地解碼所以會(huì)減少服務(wù)器壓力找都,如果圖片過(guò)大還采用base64編碼會(huì)導(dǎo)致cpu調(diào)用率上升,網(wǎng)頁(yè)加載時(shí)變卡
          limit: 8 * 1024,
          // 給圖片重命名廊酣,[hash:10]:取圖片的hash的前10位能耻,[ext]:取文件原來(lái)擴(kuò)展名
          name: '[hash:10].[ext]',
          // 問(wèn)題:因?yàn)閡rl-loader默認(rèn)使用es6模塊化解析,而html-loader引入圖片是conmonjs亡驰,解析時(shí)會(huì)出問(wèn)題:[object Module]
          // 解決:關(guān)閉url-loader的es6模塊化晓猛,使用commonjs解析
          esModule: false,
          outputPath: 'imgs',
        },
      },
      {
        test: /\.html$/,
        // 處理html文件的img圖片(負(fù)責(zé)引入img,從而能被url-loader進(jìn)行處理)
        loader: 'html-loader',
      },
      // 打包其他資源(除了html/js/css資源以外的資源)
      {
        // 排除html|js|css|less|jpg|png|gif文件
        exclude: /\.(html|js|css|less|jpg|png|gif)/,
        // file-loader:處理其他文件
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'media',
        },
      },
    ],
  },
  // plugin的配置
  plugins: [
    // html-webpack-plugin:默認(rèn)會(huì)創(chuàng)建一個(gè)空的html文件凡辱,自動(dòng)引入打包輸出的所有資源(JS/CSS)
    // 需要有結(jié)構(gòu)的HTML文件可以加一個(gè)template
    new HtmlWebpackPlugin({
      // 復(fù)制這個(gè)./src/index.html文件戒职,并自動(dòng)引入打包輸出的所有資源(JS/CSS)
      template: './src/index.html',
    }),
  ],
  // 模式
  mode: 'development', // 開發(fā)模式
  // 開發(fā)服務(wù)器 devServer:用來(lái)自動(dòng)化,不用每次修改后都重新輸入webpack打包一遍(自動(dòng)編譯透乾,自動(dòng)打開瀏覽器洪燥,自動(dòng)刷新瀏覽器)
  // 特點(diǎn):只會(huì)在內(nèi)存中編譯打包磕秤,不會(huì)有任何輸出(不會(huì)像之前那樣在外面看到打包輸出的build包,而是在內(nèi)存中蚓曼,關(guān)閉后會(huì)自動(dòng)刪除)
  // 啟動(dòng)devServer指令為:npx webpack-dev-server
  devServer: {
    // 項(xiàng)目構(gòu)建后路徑
    contentBase: resolve(__dirname, 'build'),
    // 啟動(dòng)gzip壓縮
    compress: true,
    // 端口號(hào)
    port: 3000,
    // 自動(dòng)打開瀏覽器
    open: true,
  },
}
  • 運(yùn)行項(xiàng)目的兩個(gè)指令:
    webpack 會(huì)將打包結(jié)果輸出出去(build文件夾)
    npx webpack-dev-server 只會(huì)在內(nèi)存中編譯打包亲澡,沒(méi)有輸出
  • loader 和 plugin 的不同:(plugin 一定要先引入才能使用)
    ? loader:1. 下載 2. 使用(配置 loader)
    ? plugins:1.下載 2. 引入 3. 使用

四、Webpack 生產(chǎn)環(huán)境的基本配置

而生產(chǎn)環(huán)境的配置需要考慮以下幾個(gè)方面:

  • 提取 css 成單獨(dú)文件

  • css 兼容性處理

  • 壓縮 css

  • js 語(yǔ)法檢查

  • js 兼容性處理

  • js 壓縮

  • html 壓縮

    下面是一個(gè)基本的生產(chǎn)環(huán)境下的webpack.config.js配置

const { resolve } = require('path')
const MiniCssExtractorPlugin = require('mini-css-extract-plugin')
const OptimiziCssAssetsWebpackPlugin = require('optimizi-css-assets-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

// 定義node.js的環(huán)境變量纫版,決定使用browserslist的哪個(gè)環(huán)境
process.env.NODE_ENV = 'production'

// 復(fù)用loader的寫法
const commonCssLoader = [
  // 這個(gè)loader取代style-loader床绪。作用:提取js中的css成單獨(dú)文件然后通過(guò)link加載
  MiniCssExtractPlugin.loader,
  // css-loader:將css文件整合到j(luò)s文件中
  // 經(jīng)過(guò)css-loader處理后,樣式文件是在js文件中的
  // 問(wèn)題:1.js文件體積會(huì)很大2.需要先加載js再動(dòng)態(tài)創(chuàng)建style標(biāo)簽其弊,樣式渲染速度就慢癞己,會(huì)出現(xiàn)閃屏現(xiàn)象
  // 解決:用MiniCssExtractPlugin.loader替代style-loader
  'css-loader',
  /*
    postcss-loader:css兼容性處理:postcss --> 需要安裝:postcss-loader postcss-preset-env
    postcss需要通過(guò)package.json中browserslist里面的配置加載指定的css兼容性樣式
    在package.json中定義browserslist:
    "browserslist": {
      // 開發(fā)環(huán)境 --> 設(shè)置node環(huán)境變量:process.env.NODE_ENV = development
      "development": [ // 只需要可以運(yùn)行即可
        "last 1 chrome version",
        "last 1 firefox version",
        "last 1 safari version"
      ],
      // 生產(chǎn)環(huán)境。默認(rèn)是生產(chǎn)環(huán)境
      "production": [ // 需要滿足絕大多數(shù)瀏覽器的兼容
        ">0.2%",
        "not dead",
        "not op_mini all"
      ]
    },
  */
  {
    loader: 'postcss-loader',
    options: {
      ident: 'postcss', // 基本寫法
      plugins: () => [
        // postcss的插件
        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'],
      },
      /*
        正常來(lái)講梭伐,一個(gè)文件只能被一個(gè)loader處理
        當(dāng)一個(gè)文件要被多個(gè)loader處理痹雅,那么一定要指定loader執(zhí)行的先后順序
        先執(zhí)行eslint再執(zhí)行babel(用enforce)
      */
      {
        /*
          js的語(yǔ)法檢查: 需要下載 eslint-loader eslint
          注意:只檢查自己寫的源代碼,第三方的庫(kù)是不用檢查的
          airbnb(一個(gè)流行的js風(fēng)格) --> 需要下載 eslint-config-airbnb-base eslint-plugin-import
          設(shè)置檢查規(guī)則:
            package.json中eslintConfig中設(shè)置
              "eslintConfig": {
                "extends": "airbnb-base"糊识, // 繼承airbnb的風(fēng)格規(guī)范
                "env": {
                  "browser": true // 可以使用瀏覽器中的全局變量(使用window不會(huì)報(bào)錯(cuò))
                }
              }
        */
        test: /\.js$/,
        exclude: /node_modules/, // 忽略node_modules
        enforce: 'pre', // 優(yōu)先執(zhí)行
        loader: 'eslint-loader',
        options: {
          // 自動(dòng)修復(fù)
          fix: true,
        },
      },
      /*
        js兼容性處理:需要下載 babel-loader @babel/core
          1. 基本js兼容性處理 --> @babel/preset-env
            問(wèn)題:只能轉(zhuǎn)換基本語(yǔ)法绩社,如promise高級(jí)語(yǔ)法不能轉(zhuǎn)換
          2. 全部js兼容性處理 --> @babel/polyfill
            問(wèn)題:只要解決部分兼容性問(wèn)題,但是將所有兼容性代碼全部引入赂苗,體積太大了
          3. 需要做兼容性處理的就做:按需加載  --> core-js
      */
      {
        // 第三種方式:按需加載
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          // 預(yù)設(shè):指示babel做怎樣的兼容性處理
          presets: [
            '@babel/preset-env', // 基本預(yù)設(shè)
            {
              useBuiltIns: 'usage', //按需加載
              corejs: { version: 3 }, // 指定core-js版本
              targets: { // 指定兼容到什么版本的瀏覽器
                chrome: '60',
                firefox: '50',
                ie: '9',
                safari: '10',
                edge: '17'
              },
            },
          ],
        },
      },
      {
        // 圖片處理
        test: /\.(jpg|png|gif)/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[ext]',
          outputPath: 'imgs',
          esModule: false, // 關(guān)閉url-loader默認(rèn)使用的es6模塊化解析
        },
      },
      // html中的圖片處理
      {
        test: /\.html$/,
        loader: 'html-loader',
      },
      // 處理其他文件
      {
        exclude: /\.(js|css|less|html|jpg|png|gif)/,
        loader: 'file-loader',
        options: {
          outputPath: 'media',
        },
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      // 對(duì)輸出的css文件進(jìn)行重命名
      filename: 'css/built.css',
    }),
    // 壓縮css
    new OptimiziCssAssetsWebpackPlugin(),
    // HtmlWebpackPlugin:html文件的打包和壓縮處理
    // 通過(guò)這個(gè)插件會(huì)自動(dòng)將單獨(dú)打包的樣式文件通過(guò)link標(biāo)簽引入
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // 壓縮html代碼
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注釋
        removeComments: true,
      },
    }),
  ],
  // 生產(chǎn)環(huán)境下會(huì)自動(dòng)壓縮js代碼
  mode: 'production',
}

五愉耙、Webpack 優(yōu)化配置

5.1 開發(fā)環(huán)境性能優(yōu)化

5.1.1 HMR(模塊熱替換)

HMR: hot module replacement 熱模塊替換 / 模塊熱替換
作用:一個(gè)模塊發(fā)生變化,只會(huì)重新打包構(gòu)建這一個(gè)模塊(而不是打包所有模塊) 拌滋,極大提升構(gòu)建速度
代碼:只需要在 devServer 中設(shè)置 hot 為 true朴沿,就會(huì)自動(dòng)開啟HMR功能(只能在開發(fā)模式下使用)

devServer: {
 contentBase: resolve(__dirname, 'build'),
 compress: true,
 port: 3000,
 open: true,
 // 開啟HMR功能
 // 當(dāng)修改了webpack配置,新配置要想生效败砂,必須重啟webpack服務(wù)
 hot: true
}

每種文件實(shí)現(xiàn)熱模塊替換的情況:

  • 樣式文件:可以使用HMR功能赌渣,因?yàn)殚_發(fā)環(huán)境下使用的 style-loader 內(nèi)部默認(rèn)實(shí)現(xiàn)了熱模塊替換功能
  • js 文件:默認(rèn)不能使用HMR功能(修改一個(gè) js 模塊所有 js 模塊都會(huì)刷新)
    --> 實(shí)現(xiàn) HMR 需要修改 js 代碼(添加支持 HMR 功能的代碼)
// 綁定
if (module.hot) {
  // 一旦 module.hot 為true,說(shuō)明開啟了HMR功能昌犹。 --> 讓HMR功能代碼生效
  module.hot.accept('./print.js', function() {
    // 方法會(huì)監(jiān)聽 print.js 文件的變化坚芜,一旦發(fā)生變化,只有這個(gè)模塊會(huì)重新打包構(gòu)建斜姥,其他模塊不會(huì)货岭。
    // 會(huì)執(zhí)行后面的回調(diào)函數(shù)
    print();
  });
}

注意:HMR 功能對(duì) js 的處理,只能處理非入口 js 文件的其他文件疾渴。

  • html 文件: 默認(rèn)不能使用 HMR 功能(html 不用做 HMR 功能,因?yàn)橹挥幸粋€(gè) html 文件屯仗,不需要再優(yōu)化)
    使用 HMR 會(huì)導(dǎo)致問(wèn)題:html 文件不能熱更新了(不會(huì)自動(dòng)打包構(gòu)建)
    解決:修改 entry 入口搞坝,將 html 文件引入(這樣 html 修改整體刷新)
entry: ['./src/js/index.js', './src/index.html']

5.1.2 source-map

source-map:一種提供源代碼到構(gòu)建后代碼的映射的技術(shù) (如果構(gòu)建后代碼出錯(cuò)了,通過(guò)映射可以追蹤源代碼錯(cuò)誤)
參數(shù):[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
代碼:

devtool: 'eval-source-map'

可選方案:[生成source-map的位置|給出的錯(cuò)誤代碼信息]

  • source-map:外部魁袜,錯(cuò)誤代碼準(zhǔn)確信息 和 源代碼的錯(cuò)誤位置

  • inline-source-map:內(nèi)聯(lián)桩撮,只生成一個(gè)內(nèi)聯(lián) source-map敦第,錯(cuò)誤代碼準(zhǔn)確信息 和 源代碼的錯(cuò)誤位置

  • hidden-source-map:外部,錯(cuò)誤代碼錯(cuò)誤原因店量,但是沒(méi)有錯(cuò)誤位置(為了隱藏源代碼)芜果,不能追蹤源代碼錯(cuò)誤,只能提示到構(gòu)建后代碼的錯(cuò)誤位置

  • eval-source-map:內(nèi)聯(lián)融师,每一個(gè)文件都生成對(duì)應(yīng)的 source-map右钾,都在 eval 中,錯(cuò)誤代碼準(zhǔn)確信息 和 源代碼的錯(cuò)誤位

  • nosources-source-map:外部聚磺,錯(cuò)誤代碼準(zhǔn)確信息某残,但是沒(méi)有任何源代碼信息(為了隱藏源代碼)

  • cheap-source-map:外部氧猬,錯(cuò)誤代碼準(zhǔn)確信息 和 源代碼的錯(cuò)誤位置,只能把錯(cuò)誤精確到整行脆烟,忽略列

  • cheap-module-source-map:外部,錯(cuò)誤代碼準(zhǔn)確信息 和 源代碼的錯(cuò)誤位置房待,module 會(huì)加入 loader 的 source-map

    內(nèi)聯(lián) 和 外部的區(qū)別:1. 外部生成了文件邢羔,內(nèi)聯(lián)沒(méi)有 2. 內(nèi)聯(lián)構(gòu)建速度更快

    開發(fā)/生產(chǎn)環(huán)境可做的選擇:

    開發(fā)環(huán)境:需要考慮速度快,調(diào)試更友好

  • 速度快( eval > inline > cheap >... )

    1. eval-cheap-souce-map
    2. eval-source-map
  • 調(diào)試更友好

    1. souce-map
    2. cheap-module-souce-map
    3. cheap-souce-map

    最終得出最好的兩種方案 --> eval-source-map(完整度高桑孩,內(nèi)聯(lián)速度快) / eval-cheap-module-souce-map(錯(cuò)誤提示忽略列但是包含其他信息拜鹤,內(nèi)聯(lián)速度快)

    生產(chǎn)環(huán)境:需要考慮源代碼要不要隱藏,調(diào)試要不要更友好

  • 內(nèi)聯(lián)會(huì)讓代碼體積變大洼怔,所以在生產(chǎn)環(huán)境不用內(nèi)聯(lián)

  • 隱藏源代碼

    1. nosources-source-map 全部隱藏
    2. hidden-source-map 只隱藏源代碼署惯,會(huì)提示構(gòu)建后代碼錯(cuò)誤信息
      最終得出最好的兩種方案 --> source-map(最完整) / cheap-module-souce-map(錯(cuò)誤提示一整行忽略列)

    5.2 生產(chǎn)環(huán)境性能優(yōu)化

    5.2.1 優(yōu)化打包構(gòu)建速度

    5.2.1.1 oneOf

    oneOf:匹配到 loader 后就不再向后進(jìn)行匹配,優(yōu)化生產(chǎn)環(huán)境的打包構(gòu)建速度

    代碼:

module: {
  rules: [
    {
      // js 語(yǔ)法檢查
      test: /\.js$/,
      exclude: /node_modules/,
      // 優(yōu)先執(zhí)行
      enforce: 'pre',
      loader: 'eslint-loader',
      options: {
        fix: true
      }
    },
    {
      // oneOf 優(yōu)化生產(chǎn)環(huán)境的打包構(gòu)建速度
      // 以下loader只會(huì)匹配一個(gè)(匹配到了后就不會(huì)再往下匹配了)
      // 注意:不能有兩個(gè)配置處理同一種類型文件(所以把eslint-loader提取出去放外面)
      oneOf: [
        {
          test: /\.css$/,
          use: [...commonCssLoader]
        },
        {
          test: /\.less$/,
          use: [...commonCssLoader, 'less-loader']
        },
        {
          // js 兼容性處理
          test: /\.js$/,
          exclude: /node_modules/,
          loader: 'babel-loader',
          options: {
            presets: [
              [
                '@babel/preset-env',
                {
                  useBuiltIns: 'usage',
                  corejs: {version: 3},
                  targets: {
                    chrome: '60',
                    firefox: '50'
                  }
                }
              ]
            ]
          }
        },
        {
          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: 'media'
          }
        }
      ]
    }
  ]
},

5.2.1.2 babel 緩存

babel 緩存:類似 HMR镣隶,將 babel 處理后的資源緩存起來(lái)(哪里的 js 改變就更新哪里极谊,其他 js 還是用之前緩存的資源),讓第二次打包構(gòu)建速度更快

代碼:

{
  test: /\.js$/,
  exclude: /node_modules/,
  loader: 'babel-loader',
  options: {
    presets: [
      [
        '@babel/preset-env',
        {
          useBuiltIns: 'usage',
          corejs: { version: 3 },
          targets: {
            chrome: '60',
            firefox: '50'
          }
        }
      ]
    ],
    // 開啟babel緩存
    // 第二次構(gòu)建時(shí)安岂,會(huì)讀取之前的緩存
    cacheDirectory: true
  }
},

文件資源緩存

文件名不變轻猖,就不會(huì)重新請(qǐng)求,而是再次用之前緩存的資源

1.hash: 每次 wepack 打包時(shí)會(huì)生成一個(gè)唯一的 hash 值域那。

? 問(wèn)題:重新打包咙边,所有文件的 hsah 值都改變,會(huì)導(dǎo)致所有緩存失效次员。(可能只改動(dòng)了一個(gè)文件)

2.chunkhash:根據(jù) chunk 生成的 hash 值败许。來(lái)源于同一個(gè) chunk的 hash 值一樣

? 問(wèn)題:js 和 css 來(lái)自同一個(gè)chunk,hash 值是一樣的(因?yàn)?css-loader 會(huì)將 css 文件加載到 js 中淑蔚,所以同屬于一個(gè)chunk)

3.contenthash: 根據(jù)文件的內(nèi)容生成 hash 值市殷。不同文件 hash 值一定不一樣(文件內(nèi)容修改,文件名里的 hash 才會(huì)改變)

修改 css 文件內(nèi)容刹衫,打包后的 css 文件名 hash 值就改變醋寝,而 js 文件沒(méi)有改變 hash 值就不變搞挣,這樣 css 和 js 緩存就會(huì)分開判斷要不要重新請(qǐng)求資源 --> 讓代碼上線運(yùn)行緩存更好使用

5.2.1.3 多進(jìn)程打包

多進(jìn)程打包:某個(gè)任務(wù)消耗時(shí)間較長(zhǎng)會(huì)卡頓,多進(jìn)程可以同一時(shí)間干多件事音羞,效率更高囱桨。

優(yōu)點(diǎn)是提升打包速度,缺點(diǎn)是每個(gè)進(jìn)程的開啟和交流都會(huì)有開銷(babel-loader消耗時(shí)間最久嗅绰,所以使用thread-loader針對(duì)其進(jìn)行優(yōu)化)

{
  test: /\.js$/,
  exclude: /node_modules/,
  use: [
    /* 
      thread-loader會(huì)對(duì)其后面的loader(這里是babel-loader)開啟多進(jìn)程打包舍肠。 
      進(jìn)程啟動(dòng)大概為600ms,進(jìn)程通信也有開銷办陷。(啟動(dòng)的開銷比較昂貴貌夕,不要濫用)
      只有工作消耗時(shí)間比較長(zhǎng),才需要多進(jìn)程打包
    */
    {
      loader: 'thread-loader',
      options: {
        workers: 2 // 進(jìn)程2個(gè)
      }
    },
    {
      loader: 'babel-loader',
      options: {
        presets: [
          [
            '@babel/preset-env',
            {
              useBuiltIns: 'usage',
              corejs: { version: 3 },
              targets: {
                chrome: '60',
                firefox: '50'
              }
            }
          ]
        ],
        // 開啟babel緩存
        // 第二次構(gòu)建時(shí)民镜,會(huì)讀取之前的緩存
        cacheDirectory: true
      }
    }
  ]
},

5.2.1.4 externals

externals:讓某些庫(kù)不打包啡专,通過(guò) cdn 引入
webpack.config.js 中配置:

externals: {
  // 拒絕jQuery被打包進(jìn)來(lái)(通過(guò)cdn引入,速度會(huì)快一些)
  // 忽略的庫(kù)名 -- npm包名
  jquery: 'jQuery'
}

需要在 index.html 中通過(guò) cdn 引入:

<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>

5.2.1.5 dll

dll:讓某些庫(kù)單獨(dú)打包制圈,后直接引入到 build 中们童。可以在 code split 分割出 node_modules 后再用 dll 更細(xì)的分割鲸鹦,優(yōu)化代碼運(yùn)行的性能慧库。
webpack.dll.js 配置:(將 jquery 單獨(dú)打包)

/*
  node_modules的庫(kù)會(huì)打包到一起,但是很多庫(kù)的時(shí)候打包輸出的js文件就太大了
  使用dll技術(shù)馋嗜,對(duì)某些庫(kù)(第三方庫(kù):jquery齐板、react、vue...)進(jìn)行單獨(dú)打包
  當(dāng)運(yùn)行webpack時(shí)葛菇,默認(rèn)查找webpack.config.js配置文件
  需求:需要運(yùn)行webpack.dll.js文件
    --> webpack --config webpack.dll.js(運(yùn)行這個(gè)指令表示以這個(gè)配置文件打包)
*/
const { resolve } = require('path');
const webpack = require('webpack');

module.exports = {
  entry: {
    // 最終打包生成的[name] --> jquery
    // ['jquery] --> 要打包的庫(kù)是jquery
    jquery: ['jquery']
  },
  output: {
    // 輸出出口指定
    filename: '[name].js', // name就是jquery
    path: resolve(__dirname, 'dll'), // 打包到dll目錄下
    library: '[name]_[hash]', // 打包的庫(kù)里面向外暴露出去的內(nèi)容叫什么名字
  },
  plugins: [
    // 打包生成一個(gè)manifest.json --> 提供jquery的映射關(guān)系(告訴webpack:jquery之后不需要再打包和暴露內(nèi)容的名稱)
    new webpack.DllPlugin({
      name: '[name]_[hash]', // 映射庫(kù)的暴露的內(nèi)容名稱
      path: resolve(__dirname, 'dll/manifest.json') // 輸出文件路徑
    })
  ],
  mode: 'production'
};

webpack.config.js 配置:(告訴 webpack 不需要再打包 jquery甘磨,并將之前打包好的 jquery 跟其他打包好的資源一同輸出到 build 目錄下)

// 引入插件
const webpack = require('webpack');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');

// plugins中配置:
plugins: [
  new HtmlWebpackPlugin({
    template: './src/index.html'
  }),
  // 告訴webpack哪些庫(kù)不參與打包,同時(shí)使用時(shí)的名稱也得變
  new webpack.DllReferencePlugin({
    manifest: resolve(__dirname, 'dll/manifest.json')
  }),
  // 將某個(gè)文件打包輸出到build目錄下眯停,并在html中自動(dòng)引入該資源
  new AddAssetHtmlWebpackPlugin({
    filepath: resolve(__dirname, 'dll/jquery.js')
  })
],

5.2.2 優(yōu)化代碼運(yùn)行的性能

5.2.2.1 緩存

5.2.2.2 tree shaking(樹搖)

tree shaking:去除無(wú)用代碼
前提:1. 必須使用 ES6 模塊化 2. 開啟 production 環(huán)境 (這樣就自動(dòng)會(huì)把無(wú)用代碼去掉)
作用:減少代碼體積
在 package.json 中配置:
"sideEffects": false 表示所有代碼都沒(méi)有副作用(都可以進(jìn)行 tree shaking)
這樣會(huì)導(dǎo)致的問(wèn)題:可能會(huì)把 css / @babel/polyfill 文件干掉(副作用)
所以可以配置:"sideEffects": ["*.css", "*.less"] 不會(huì)對(duì)css/less文件tree shaking處理

5.2.2.3 code split(代碼分割)

代碼分割济舆。將打包輸出的一個(gè)大的 bundle.js 文件拆分成多個(gè)小文件,這樣可以并行加載多個(gè)文件莺债,比加載一個(gè)文件更快滋觉。
1.多入口拆分

entry: {
    // 多入口:有一個(gè)入口,最終輸出就有一個(gè)bundle
    index: './src/js/index.js',
    test: './src/js/test.js'
  },
  output: {
    // [name]:取文件名
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },

2.optimization:

optimization: {
    splitChunks: {
      chunks: 'all'
    }
  },
  • 將 node_modules 中的代碼單獨(dú)打包(大小超過(guò)30kb)
  • 自動(dòng)分析多入口chunk中齐邦,有沒(méi)有公共的文件椎侠。如果有會(huì)打包成單獨(dú)一個(gè)chunk(比如兩個(gè)模塊中都引入了jquery會(huì)被打包成單獨(dú)的文件)(大小超過(guò)30kb)
    3.import 動(dòng)態(tài)導(dǎo)入語(yǔ)法:
/*
  通過(guò)js代碼,讓某個(gè)文件被單獨(dú)打包成一個(gè)chunk
  import動(dòng)態(tài)導(dǎo)入語(yǔ)法:能將某個(gè)文件單獨(dú)打包(test文件不會(huì)和index打包在同一個(gè)文件而是單獨(dú)打包)
  webpackChunkName:指定test單獨(dú)打包后文件的名字
*/
import(/* webpackChunkName: 'test' */'./test')
  .then(({ mul, count }) => {
    // 文件加載成功~
    // eslint-disable-next-line
    console.log(mul(2, 5));
  })
  .catch(() => {
    // eslint-disable-next-line
    console.log('文件加載失敗~');
  });

5.2.2.4 lazy loading(懶加載/預(yù)加載)

1.懶加載:當(dāng)文件需要使用時(shí)才加載(需要代碼分割)措拇。但是如果資源較大肺蔚,加載時(shí)間就會(huì)較長(zhǎng),有延遲。

2.正常加載:可以認(rèn)為是并行加載(同一時(shí)間加載多個(gè)文件)沒(méi)有先后順序宣羊,先加載了不需要的資源就會(huì)浪費(fèi)時(shí)間。

3.預(yù)加載 prefetch(兼容性很差):會(huì)在使用之前汰蜘,提前加載仇冯。等其他資源加載完畢,瀏覽器空閑了族操,再偷偷加載這個(gè)資源苛坚。這樣在使用時(shí)已經(jīng)加載好了,速度很快色难。所以在懶加載的基礎(chǔ)上加上預(yù)加載會(huì)更好泼舱。

代碼:
document.getElementById('btn').onclick = function() {
  // 將import的內(nèi)容放在異步回調(diào)函數(shù)中使用,點(diǎn)擊按鈕枷莉,test.js才會(huì)被加載(不會(huì)重復(fù)加載)
  // webpackPrefetch: true表示開啟預(yù)加載
  import(/* webpackChunkName: 'test', webpackPrefetch: true */'./test').then(({ mul }) => {
    console.log(mul(4, 5));
  });
  import('./test').then(({ mul }) => {
    console.log(mul(2, 5))
  })
};

5.2.2.5 pwa(離線可訪問(wèn)技術(shù))

pwa:離線可訪問(wèn)技術(shù)(漸進(jìn)式網(wǎng)絡(luò)開發(fā)應(yīng)用程序)娇昙,使用 serviceworker 和 workbox 技術(shù)。優(yōu)點(diǎn)是離線也能訪問(wèn)笤妙,缺點(diǎn)是兼容性差冒掌。
webpack.config.js 中配置:

const WorkboxWebpackPlugin = require('workbox-webpack-plugin'); // 引入插件

// plugins中加入:
new WorkboxWebpackPlugin.GenerateSW({
  /*
    1. 幫助serviceworker快速啟動(dòng)
    2. 刪除舊的 serviceworker

    生成一個(gè) serviceworker 配置文件
  */
  clientsClaim: true,
  skipWaiting: true
})

index.js 中還需要寫一段代碼來(lái)激活它的使用:

/*
  1. eslint不認(rèn)識(shí) window、navigator全局變量
    解決:需要修改package.json中eslintConfig配置
    "env": {
      "browser": true // 支持瀏覽器端全局變量
    }
  2. sw代碼必須運(yùn)行在服務(wù)器上
    --> nodejs
    或-->
      npm i serve -g
      serve -s build 啟動(dòng)服務(wù)器蹲盘,將打包輸出的build目錄下所有資源作為靜態(tài)資源暴露出去
*/
if ('serviceWorker' in navigator) { // 處理兼容性問(wèn)題
  window.addEventListener('load', () => {
    navigator.serviceWorker
      .register('/service-worker.js') // 注冊(cè)serviceWorker
      .then(() => {
        console.log('sw注冊(cè)成功了~');
      })
      .catch(() => {
        console.log('sw注冊(cè)失敗了~');
      });
  });
}

六股毫、Webpack 配置詳情

6.1 entry

entry: 入口起點(diǎn)

  1. string --> './src/index.js',單入口
    打包形成一個(gè) chunk召衔。 輸出一個(gè) bundle 文件铃诬。此時(shí) chunk 的名稱默認(rèn)是 main

  2. array --> ['./src/index.js', './src/add.js'],多入口
    所有入口文件最終只會(huì)形成一個(gè) chunk苍凛,輸出出去只有一個(gè) bundle 文件趣席。
    (一般只用在 HMR 功能中讓 html 熱更新生效)

  3. object,多入口
    有幾個(gè)入口文件就形成幾個(gè) chunk毫深,輸出幾個(gè) bundle 文件吩坝,此時(shí) chunk 的名稱是 key 值

    --> 特殊用法:

entry: {
  // 最終只會(huì)形成一個(gè)chunk, 輸出出去只有一個(gè)bundle文件。
  index: ['./src/index.js', './src/count.js'], 
  // 形成一個(gè)chunk哑蔫,輸出一個(gè)bundle文件钉寝。
  add: './src/add.js'
}

6.2 output

output: {
  // 文件名稱(指定名稱+目錄)
  filename: 'js/[name].js',
  // 輸出文件目錄(將來(lái)所有資源輸出的公共目錄)
  path: resolve(__dirname, 'build'),
  // 所有資源引入公共路徑前綴 --> 'imgs/a.jpg' --> '/imgs/a.jpg'
  publicPath: '/',
  chunkFilename: 'js/[name]_chunk.js', // 指定非入口chunk的名稱
  library: '[name]', // 打包整個(gè)庫(kù)后向外暴露的變量名
  libraryTarget: 'window' // 變量名添加到哪個(gè)上 browser:window
  // libraryTarget: 'global' // node:global
  // libraryTarget: 'commonjs' // conmmonjs模塊 exports
},

6.3 module

module: {
  rules: [
    // loader的配置
    {
      test: /\.css$/,
      // 多個(gè)loader用use
      use: ['style-loader', 'css-loader']
    },
    {
      test: /\.js$/,
      // 排除node_modules下的js文件
      exclude: /node_modules/,
      // 只檢查src下的js文件
      include: resolve(__dirname, 'src'),
      enforce: 'pre', // 優(yōu)先執(zhí)行
      // enforce: 'post', // 延后執(zhí)行
      // 單個(gè)loader用loader
      loader: 'eslint-loader',
      options: {} // 指定配置選項(xiàng)
    },
    {
      // 以下配置只會(huì)生效一個(gè)
      oneOf: []
    }
  ]
},

6.4 resolve

// 解析模塊的規(guī)則
resolve: {
  // 配置解析模塊路徑別名: 優(yōu)點(diǎn):當(dāng)目錄層級(jí)很復(fù)雜時(shí),簡(jiǎn)寫路徑闸迷;缺點(diǎn):路徑不會(huì)提示
  alias: {
    $css: resolve(__dirname, 'src/css')
  },
  // 配置省略文件路徑的后綴名(引入時(shí)就可以不寫文件后綴名了)
  extensions: ['.js', '.json', '.jsx', '.css'],
  // 告訴 webpack 解析模塊應(yīng)該去找哪個(gè)目錄
  modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
}

這樣配置后嵌纲,引入文件就可以這樣簡(jiǎn)寫:import '$css/index';

6.5 dev server

devServer: {
  // 運(yùn)行代碼所在的目錄
  contentBase: resolve(__dirname, 'build'),
  // 監(jiān)視contentBase目錄下的所有文件,一旦文件變化就會(huì)reload
  watchContentBase: true,
  watchOptions: {
    // 忽略文件
    ignored: /node_modules/
  },
  // 啟動(dòng)gzip壓縮
  compress: true,
  // 端口號(hào)
  port: 5000,
  // 域名
  host: 'localhost',
  // 自動(dòng)打開瀏覽器
  open: true,
  // 開啟HMR功能
  hot: true,
  // 不要顯示啟動(dòng)服務(wù)器日志信息
  clientLogLevel: 'none',
  // 除了一些基本信息外腥沽,其他內(nèi)容都不要顯示
  quiet: true,
  // 如果出錯(cuò)了逮走,不要全屏提示
  overlay: false,
  // 服務(wù)器代理,--> 解決開發(fā)環(huán)境跨域問(wèn)題
  proxy: {
    // 一旦devServer(5000)服務(wù)器接收到/api/xxx的請(qǐng)求今阳,就會(huì)把請(qǐng)求轉(zhuǎn)發(fā)到另外一個(gè)服務(wù)器3000
    '/api': {
      target: 'http://localhost:3000',
      // 發(fā)送請(qǐng)求時(shí)师溅,請(qǐng)求路徑重寫:將/api/xxx --> /xxx (去掉/api)
      pathRewrite: {
        '^/api': ''
      }
    }
  }
}

其中茅信,跨域問(wèn)題:同源策略中不同的協(xié)議、端口號(hào)墓臭、域名就會(huì)產(chǎn)生跨域蘸鲸。
正常的瀏覽器和服務(wù)器之間有跨域,但是服務(wù)器之間沒(méi)有跨域窿锉。代碼通過(guò)代理服務(wù)器運(yùn)行酌摇,所以瀏覽器和代理服務(wù)器之間沒(méi)有跨域,瀏覽器把請(qǐng)求發(fā)送到代理服務(wù)器上嗡载,代理服務(wù)器替你轉(zhuǎn)發(fā)到另外一個(gè)服務(wù)器上窑多,服務(wù)器之間沒(méi)有跨域,所以請(qǐng)求成功洼滚。代理服務(wù)器再把接收到的響應(yīng)響應(yīng)給瀏覽器埂息。這樣就解決開發(fā)環(huán)境下的跨域問(wèn)題。

6.6 optimization

contenthash 緩存會(huì)導(dǎo)致一個(gè)問(wèn)題:修改 a 文件導(dǎo)致 b 文件 contenthash 變化判沟。
因?yàn)樵?index.js 中引入 a.js耿芹,打包后 index.js 中記錄了 a.js 的 hash 值,而 a.js 改變挪哄,其重新打包后的 hash 改變吧秕,導(dǎo)致 index.js 文件內(nèi)容中記錄的 a.js 的 hash 也改變,從而重新打包后 index.js 的 hash 值也會(huì)變迹炼,這樣就會(huì)使緩存失效砸彬。(改變的是a.js文件但是 index.js 文件的 hash 值也改變了)
解決辦法:runtimeChunk --> 將當(dāng)前模塊記錄其他模塊的 hash 單獨(dú)打包為一個(gè)文件 runtime,這樣 a.js 的 hash 改變只會(huì)影響 runtime 文件斯入,不會(huì)影響到 index.js 文件

output: {
  filename: 'js/[name].[contenthash:10].js',
  path: resolve(__dirname, 'build'),
  chunkFilename: 'js/[name].[contenthash:10]_chunk.js' // 指定非入口文件的其他chunk的名字加_chunk
},
optimization: {
  splitChunks: {
    chunks: 'all',
    /* 以下都是splitChunks默認(rèn)配置砂碉,可以不寫
    miniSize: 30 * 1024, // 分割的chunk最小為30kb(大于30kb的才分割)
    maxSize: 0, // 最大沒(méi)有限制
    minChunks: 1, // 要提取的chunk最少被引用1次
    maxAsyncRequests: 5, // 按需加載時(shí)并行加載的文件的最大數(shù)量為5
    maxInitialRequests: 3, // 入口js文件最大并行請(qǐng)求數(shù)量
    automaticNameDelimiter: '~', // 名稱連接符
    name: true, // 可以使用命名規(guī)則
    cacheGroups: { // 分割chunk的組
      vendors: {
        // node_modules中的文件會(huì)被打包到vendors組的chunk中,--> vendors~xxx.js
        // 滿足上面的公共規(guī)則刻两,大小超過(guò)30kb增蹭、至少被引用一次
        test: /[\\/]node_modules[\\/]/,
        // 優(yōu)先級(jí)
        priority: -10
      },
      default: {
        // 要提取的chunk最少被引用2次
        minChunks: 2,
        prority: -20,
        // 如果當(dāng)前要打包的模塊和之前已經(jīng)被提取的模塊是同一個(gè),就會(huì)復(fù)用磅摹,而不是重新打包
        reuseExistingChunk: true
      }
    } */
  },
  // 將index.js記錄的a.js的hash值單獨(dú)打包到runtime文件中
  runtimeChunk: {
    name: entrypoint => `runtime-${entrypoint.name}`
  },
  minimizer: [
    // 配置生產(chǎn)環(huán)境的壓縮方案:js/css
    new TerserWebpackPlugin({
      // 開啟緩存
      cache: true,
      // 開啟多進(jìn)程打包
      parallel: true,
      // 啟用sourceMap(否則會(huì)被壓縮掉)
      sourceMap: true
    })
  ]
}

七滋迈、Webpack5 介紹和使用

此版本重點(diǎn)關(guān)注以下內(nèi)容:

  • 通過(guò)持久緩存提高構(gòu)建性能.

  • 使用更好的算法和默認(rèn)值來(lái)改善長(zhǎng)期緩存.

  • 通過(guò)更好的樹搖和代碼生成來(lái)改善捆綁包大小.

  • 清除處于怪異狀態(tài)的內(nèi)部結(jié)構(gòu),同時(shí)在 v4 中實(shí)現(xiàn)功能而不引入任何重大更改.

  • 通過(guò)引入重大更改來(lái)為將來(lái)的功能做準(zhǔn)備户誓,以使我們能夠盡可能長(zhǎng)時(shí)間地使用 v5.

    下載

    npm i webpack@next webpack-cli -D

    自動(dòng)刪除 Node.js Polyfills

    早期饼灿,webpack 的目標(biāo)是允許在瀏覽器中運(yùn)行大多數(shù) node.js 模塊,但是模塊格局發(fā)生了變化帝美,許多模塊用途現(xiàn)在主要是為前端目的而編寫的碍彭。webpack <= 4 附帶了許多 node.js 核心模塊的 polyfill,一旦模塊使用任何核心模塊(即 crypto 模塊),這些模塊就會(huì)自動(dòng)應(yīng)用庇忌。

    盡管這使使用為 node.js 編寫的模塊變得容易舞箍,但它會(huì)將這些巨大的 polyfill 添加到包中。在許多情況下皆疹,這些 polyfill 是不必要的创译。

    webpack 5 會(huì)自動(dòng)停止填充這些核心模塊,并專注于與前端兼容的模塊墙基。

    遷移:

  • 盡可能嘗試使用與前端兼容的模塊。

  • 可以為 node.js 核心模塊手動(dòng)添加一個(gè) polyfill刷喜。錯(cuò)誤消息將提示如何實(shí)現(xiàn)該目標(biāo)残制。

Chunk 和模塊 ID
添加了用于長(zhǎng)期緩存的新算法。在生產(chǎn)模式下默認(rèn)情況下啟用這些功能掖疮。

chunkIds: "deterministic", moduleIds: "deterministic"

Chunk ID

你可以不用使用 import(/* webpackChunkName: "name" */ "module") 在開發(fā)環(huán)境來(lái)為 chunk 命名初茶,生產(chǎn)環(huán)境還是有必要的
webpack 內(nèi)部有 chunk 命名規(guī)則,不再是以 id(0, 1, 2)命名了

Tree Shaking

  1. webpack 現(xiàn)在能夠處理對(duì)嵌套模塊的 tree shaking
// inner.js
export const a = 1;
export const b = 2;

// module.js
import * as inner from './inner';
export { inner };

// user.js
import * as module from './module';
console.log(module.inner.a);

在生產(chǎn)環(huán)境中, inner 模塊暴露的 b 會(huì)被刪除

  1. webpack 現(xiàn)在能夠多個(gè)模塊之前的關(guān)系
import { something } from './something';

function usingSomething() {
  return something;
}

export function test() {
  return usingSomething();
}

當(dāng)設(shè)置了"sideEffects": false時(shí)浊闪,一旦發(fā)現(xiàn)test方法沒(méi)有使用恼布,不但刪除test,還會(huì)刪除"./something"

  1. webpack 現(xiàn)在能處理對(duì) Commonjs 的 tree shaking

Output

SplitChunk

// webpack4
minSize: 30000;
// webpack5
minSize: {
  javascript: 30000,
  style: 50000,
}

webpack 4 默認(rèn)只能輸出 ES5 代碼

webpack 5 開始新增一個(gè)屬性 output.ecmaVersion, 可以生成 ES5 和 ES6 / ES2015 代碼.
如:output.ecmaVersion: 2015

Caching

// 配置緩存
cache: {
  // 磁盤存儲(chǔ)
  type: "filesystem",
  buildDependencies: {
    // 當(dāng)配置修改時(shí)搁宾,緩存失效
    config: [__filename]
  }
}

緩存將存儲(chǔ)到 node_modules/.cache/webpack

監(jiān)視輸出文件

之前 webpack 總是在第一次構(gòu)建時(shí)輸出全部文件折汞,但是監(jiān)視重新構(gòu)建時(shí)會(huì)只更新修改的文件。

此次更新在第一次構(gòu)建時(shí)會(huì)找到輸出文件看是否有變化盖腿,從而決定要不要輸出全部文件爽待。

默認(rèn)值

  • entry: "./src/index.js

  • output.path: path.resolve(__dirname, "dist")

  • output.filename: "[name].js"

轉(zhuǎn)載

Webpack入門-學(xué)習(xí)總結(jié)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市翩腐,隨后出現(xiàn)的幾起案子鸟款,更是在濱河造成了極大的恐慌,老刑警劉巖茂卦,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件何什,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡等龙,警方通過(guò)查閱死者的電腦和手機(jī)处渣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)而咆,“玉大人霍比,你說(shuō)我怎么就攤上這事”┍福” “怎么了悠瞬?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我浅妆,道長(zhǎng)望迎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任凌外,我火速辦了婚禮辩尊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘康辑。我一直安慰自己摄欲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布疮薇。 她就那樣靜靜地躺著胸墙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪按咒。 梳的紋絲不亂的頭發(fā)上迟隅,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音励七,去河邊找鬼智袭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛掠抬,可吹牛的內(nèi)容都是我干的吼野。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼剿另,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼箫锤!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起雨女,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤谚攒,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后氛堕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體馏臭,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年讼稚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了括儒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡锐想,死狀恐怖帮寻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赠摇,我是刑警寧澤固逗,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布浅蚪,位于F島的核電站,受9級(jí)特大地震影響烫罩,放射性物質(zhì)發(fā)生泄漏惜傲。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一贝攒、第九天 我趴在偏房一處隱蔽的房頂上張望盗誊。 院中可真熱鬧,春花似錦隘弊、人聲如沸哈踱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)嚣鄙。三九已至,卻和暖如春串结,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舅列。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工肌割, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人帐要。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓把敞,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親榨惠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子奋早,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • GitChat技術(shù)雜談 前言 本文較長(zhǎng),為了節(jié)省你的閱讀時(shí)間赠橙,在文前列寫作思路如下: 什么是 webpack耽装,它要...
    蕭玄辭閱讀 12,691評(píng)論 7 110
  • 2018年8月25日更新,目前 webpack 已經(jīng)更新值 4.17.1 期揪,本文所用到的各種庫(kù)或多或少有些過(guò)時(shí)掉奄,跟...
    AizawaSayo閱讀 257評(píng)論 0 2
  • Concepts Webpack是一個(gè)JavaScript應(yīng)用程序的模塊打包工具,能將項(xiàng)目的依賴關(guān)系構(gòu)建成圖譜凤薛,它...
    tangyefei閱讀 428評(píng)論 0 2
  • 2017年12月7日更新姓建,添加了clean-webpack-plugin,babel-env-preset,添加本...
    ZombieBrandg閱讀 1,163評(píng)論 0 19
  • 代碼均放在git倉(cāng)庫(kù) 一、核心概念 Webpack具有四個(gè)核心的概念缤苫,想要入門Webpack就得先好好了解這四個(gè)核...
    DC_er閱讀 346評(píng)論 0 0