1. 程式人生 > 其它 >webpack 優化配置

webpack 優化配置

技術標籤:自動化構建工具# webpack

目錄

1 HMR

  1. 建立檔案
    在這裡插入圖片描述
    HMR: hot module replacement 熱模組替換 / 模組熱替換
    作用:一個模組發生變化,只會重新打包這一個模組(而不是打包所有模組) 極大提升構建速度

    樣式檔案:可以使用HMR功能:因為style-loader內部實現了~
    js檔案:預設不能使用HMR功能 --> 需要修改js程式碼,新增支援HMR功能的程式碼

    注意:HMR功能對js的處理,只能處理非入口js檔案的其他檔案。
    html檔案: 預設不能使用HMR功能.同時會導致問題:html檔案不能熱更新了~ (不用做HMR功能)
    解決:修改entry入口,將html檔案引入

  2. 修改配置檔案

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

module.exports = {
    entry: ['./src/js/index.js', './src/index.html'],
    output: {
        filename:
'js/built.js', path: resolve(__dirname, 'build') }, module: { rules: [ // loader的配置 { // 處理less資源 test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader'] }, { // 處理css資源
test: /\.css$/, use: ['style-loader', 'css-loader'] }, { // 處理圖片資源 test: /\.(jpg|png|gif)$/, loader: 'url-loader', options: { limit: 8 * 1024, name: '[hash:10].[ext]', // 關閉es6模組化 esModule: false, outputPath: 'imgs' } }, { // 處理html中img資源 test: /\.html$/, loader: 'html-loader' }, { // 處理其他資源 exclude: /\.(html|js|css|less|jpg|png|gif)/, loader: 'file-loader', options: { name: '[hash:10].[ext]', outputPath: 'media' } } ] }, plugins: [ // plugins的配置 new HtmlWebpackPlugin({ template: './src/index.html' }) ], mode: 'development', devServer: { contentBase: resolve(__dirname, 'build'), compress: true, port: 3000, open: true, // 開啟HMR功能 // 當修改了webpack配置,新配置要想生效,必須重新webpack服務 hot: true } };
  1. 執行指令: webpack

2 source-map

  1. 建立檔案
    在這裡插入圖片描述
    source-map: 一種 提供原始碼到構建後代碼對映 技術 (如果構建後代碼出錯了,通過對映可以追蹤原始碼錯誤)

    [inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map

    • source-map:外部
      錯誤程式碼準確資訊 和 原始碼的錯誤位置
    • inline-source-map:內聯
      只生成一個內聯source-map
      錯誤程式碼準確資訊 和 原始碼的錯誤位置
    • hidden-source-map:外部
      錯誤程式碼錯誤原因,但是沒有錯誤位置
      不能追蹤原始碼錯誤,只能提示到構建後代碼的錯誤位置
    • eval-source-map:內聯
      每一個檔案都生成對應的source-map,都在eval
      錯誤程式碼準確資訊 和 原始碼的錯誤位置
    • nosources-source-map:外部
      錯誤程式碼準確資訊, 但是沒有任何原始碼資訊
    • cheap-source-map:外部
      錯誤程式碼準確資訊 和 原始碼的錯誤位置
      只能精確的行
    • cheap-module-source-map:外部
      錯誤程式碼準確資訊 和 原始碼的錯誤位置
      module會將loader的source map加入

    內聯 和 外部的區別:1. 外部生成了檔案,內聯沒有 2. 內聯構建速度更快

    開發環境:速度快,除錯更友好

    • 速度快(eval>inline>cheap>…)
      eval-cheap-souce-map
      eval-source-map
    • 除錯更友好
      souce-map
      cheap-module-souce-map
      cheap-souce-map

    –> eval-source-map / eval-cheap-module-souce-map

    生產環境:
    內聯會讓程式碼體積變大,所以在生產環境不用內聯
    nosources-source-map 全部隱藏
    hidden-source-map 只隱藏原始碼,會提示構建後代碼錯誤資訊

    –> source-map / cheap-module-souce-map

  2. 修改配置檔案

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

module.exports = {
    entry: ['./src/js/index.js', './src/index.html'],
    output: {
        filename: 'js/built.js',
        path: resolve(__dirname, 'build')
    },
    module: {
        rules: [
            // loader的配置
            {
                // 處理less資源
                test: /\.less$/,
                use: ['style-loader', 'css-loader', 'less-loader']
            },
            {
                // 處理css資源
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                // 處理圖片資源
                test: /\.(jpg|png|gif)$/,
                loader: 'url-loader',
                options: {
                    limit: 8 * 1024,
                    name: '[hash:10].[ext]',
                    // 關閉es6模組化
                    esModule: false,
                    outputPath: 'imgs'
                }
            },
            {
                // 處理html中img資源
                test: /\.html$/,
                loader: 'html-loader'
            },
            {
                // 處理其他資源
                exclude: /\.(html|js|css|less|jpg|png|gif)/,
                loader: 'file-loader',
                options: {
                    name: '[hash:10].[ext]',
                    outputPath: 'media'
                }
            }
        ]
    },
    plugins: [
        // plugins的配置
        new HtmlWebpackPlugin({
            template: './src/index.html'
        })
    ],
    mode: 'development',
    devServer: {
        contentBase: resolve(__dirname, 'build'),
        compress: true,
        port: 3000,
        open: true,
        hot: true
    },
    devtool: 'eval-source-map'
};
  1. 執行指令: webpack

3 oneOf

  1. 建立檔案
    在這裡插入圖片描述
  2. 修改配置檔案
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 = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    // 還需要在package.json中定義browserslist
    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: [
      {
        // 在package.json中eslintConfig --> airbnb
        test: /\.js$/,
        exclude: /node_modules/,
        // 優先執行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        // 以下loader只會匹配一個
        // 注意:不能有兩個配置處理同一種類型檔案
        oneOf: [
          {
            test: /\.css$/,
            use: [...commonCssLoader]
          },
          {
            test: /\.less$/,
            use: [...commonCssLoader, 'less-loader']
          },
          /*
            正常來講,一個檔案只能被一個loader處理。
            當一個檔案要被多個loader處理,那麼一定要指定loader執行的先後順序:
              先執行eslint 在執行babel
          */
          {
            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'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/built.css'
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    })
  ],
  mode: 'production'
};
  1. 執行指令:webpack

4 快取

  1. 建立檔案
    在這裡插入圖片描述
  • babel快取
    cacheDirectory: true
    –> 讓第二次打包構建速度更快
  • 檔案資源快取
    • hash: 每次wepack構建時會生成一個唯一的hash值。
      問題: 因為js和css同時使用一個hash值。
      如果重新打包,會導致所有快取失效。(可能我卻只改動一個檔案)
    • chunkhash:根據chunk生成的hash值。如果打包來源於同一個chunk,那麼hash值就一樣
      問題: js和css的hash值還是一樣的
      因為css是在js中被引入的,所以同屬於一個chunk
    • contenthash: 根據檔案的內容生成hash值。不同檔案hash值一定不一樣
      –> 讓程式碼上線執行快取更好使用
  1. 修改配置檔案
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 = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    // 還需要在package.json中定義browserslist
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [require('postcss-preset-env')()]
    }
  }
];

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        // 在package.json中eslintConfig --> airbnb
        test: /\.js$/,
        exclude: /node_modules/,
        // 優先執行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        // 以下loader只會匹配一個
        // 注意:不能有兩個配置處理同一種類型檔案
        oneOf: [
          {
            test: /\.css$/,
            use: [...commonCssLoader]
          },
          {
            test: /\.less$/,
            use: [...commonCssLoader, 'less-loader']
          },
          /*
            正常來講,一個檔案只能被一個loader處理。
            當一個檔案要被多個loader處理,那麼一定要指定loader執行的先後順序:
              先執行eslint 在執行babel
          */
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: { version: 3 },
                    targets: {
                      chrome: '60',
                      firefox: '50'
                    }
                  }
                ]
              ],
              // 開啟babel快取
              // 第二次構建時,會讀取之前的快取
              cacheDirectory: true
            }
          },
          {
            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'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/built.[contenthash:10].css'
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    })
  ],
  mode: 'production',
  devtool: 'source-map'
};

  1. 執行指令: webpack

5 tree shaking

1.建立檔案
在這裡插入圖片描述
tree shaking:去除無用程式碼
前提:1. 必須使用ES6模組化 2. 開啟production環境
作用: 減少程式碼體積

在package.json中配置
“sideEffects”: false 所有程式碼都沒有副作用(都可以進行tree shaking)
問題:可能會把css / @babel/polyfill (副作用)檔案幹掉
“sideEffects”: [".css", ".less"]

  1. 修改配置檔案
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 = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    // 還需要在package.json中定義browserslist
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [require('postcss-preset-env')()]
    }
  }
];

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        // 在package.json中eslintConfig --> airbnb
        test: /\.js$/,
        exclude: /node_modules/,
        // 優先執行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        // 以下loader只會匹配一個
        // 注意:不能有兩個配置處理同一種類型檔案
        oneOf: [
          {
            test: /\.css$/,
            use: [...commonCssLoader]
          },
          {
            test: /\.less$/,
            use: [...commonCssLoader, 'less-loader']
          },
          /*
            正常來講,一個檔案只能被一個loader處理。
            當一個檔案要被多個loader處理,那麼一定要指定loader執行的先後順序:
              先執行eslint 在執行babel
          */
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: { version: 3 },
                    targets: {
                      chrome: '60',
                      firefox: '50'
                    }
                  }
                ]
              ],
              // 開啟babel快取
              // 第二次構建時,會讀取之前的快取
              cacheDirectory: true
            }
          },
          {
            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'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/built.[contenthash:10].css'
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    })
  ],
  mode: 'production',
  devtool: 'source-map'
};
  1. 執行指令: webpack

6 code split

  1. 建立檔案
    在這裡插入圖片描述
  2. 修改配置檔案
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // 單入口
  // entry: './src/js/index.js',
  entry: {
    // 多入口:有一個入口,最終輸出就有一個bundle
    index: './src/js/index.js',
    test: './src/js/test.js'
  },
  output: {
    // [name]:取檔名
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    })
  ],
  mode: 'production'
};

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

module.exports = {
  // 單入口
  // entry: './src/js/index.js',
  entry: {
    index: './src/js/index.js',
    test: './src/js/test.js'
  },
  output: {
    // [name]:取檔名
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    })
  ],
  /*
    1. 可以將node_modules中程式碼單獨打包一個chunk最終輸出
    2. 自動分析多入口chunk中,有沒有公共的檔案。如果有會打包成單獨一個chunk
  */
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  },
  mode: 'production'
};

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

module.exports = {
  // 單入口
  entry: './src/js/index.js',
  output: {
    // [name]:取檔名
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    })
  ],
  /*
    1. 可以將node_modules中程式碼單獨打包一個chunk最終輸出
    2. 自動分析多入口chunk中,有沒有公共的檔案。如果有會打包成單獨一個chunk
  */
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  },
  mode: 'production'
};

  1. 執行指令: webpack

7 lazy loading

  1. 建立檔案
    在這裡插入圖片描述
  2. 修改配置檔案
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // 單入口
  entry: './src/js/index.js',
  output: {
    filename: 'js/[name].[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    })
  ],
  optimization: {
    splitChunks: {
      chunks: 'all'
    }
  },
  mode: 'production'
};

  1. 執行指令: webpack

8 pwa

  1. 建立檔案
    在這裡插入圖片描述
  2. 下載安裝包
    npm install --save-dev workbox-webpack-plugin
  3. 修改配置檔案
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');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');

/*
  PWA: 漸進式網路開發應用程式(離線可訪問)
    workbox --> workbox-webpack-plugin
*/

// 定義nodejs環境變數:決定使用browserslist的哪個環境
process.env.NODE_ENV = 'production';

// 複用loader
const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    // 還需要在package.json中定義browserslist
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [require('postcss-preset-env')()]
    }
  }
];

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        // 在package.json中eslintConfig --> airbnb
        test: /\.js$/,
        exclude: /node_modules/,
        // 優先執行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        // 以下loader只會匹配一個
        // 注意:不能有兩個配置處理同一種類型檔案
        oneOf: [
          {
            test: /\.css$/,
            use: [...commonCssLoader]
          },
          {
            test: /\.less$/,
            use: [...commonCssLoader, 'less-loader']
          },
          /*
            正常來講,一個檔案只能被一個loader處理。
            當一個檔案要被多個loader處理,那麼一定要指定loader執行的先後順序:
              先執行eslint 在執行babel
          */
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: { version: 3 },
                    targets: {
                      chrome: '60',
                      firefox: '50'
                    }
                  }
                ]
              ],
              // 開啟babel快取
              // 第二次構建時,會讀取之前的快取
              cacheDirectory: true
            }
          },
          {
            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'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/built.[contenthash:10].css'
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    }),
    new WorkboxWebpackPlugin.GenerateSW({
      /*
        1. 幫助serviceworker快速啟動
        2. 刪除舊的 serviceworker

        生成一個 serviceworker 配置檔案~
      */
      clientsClaim: true,
      skipWaiting: true
    })
  ],
  mode: 'production',
  devtool: 'source-map'
};

  1. 執行指令:webpack

9 多程序打包

  1. 建立檔案
    在這裡插入圖片描述
  2. 下載安裝包
    npm install --save-dev thread-loader
  3. 修改配置檔案
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');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');

/*
  PWA: 漸進式網路開發應用程式(離線可訪問)
    workbox --> workbox-webpack-plugin
*/

// 定義nodejs環境變數:決定使用browserslist的哪個環境
process.env.NODE_ENV = 'production';

// 複用loader
const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    // 還需要在package.json中定義browserslist
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [require('postcss-preset-env')()]
    }
  }
];

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        // 在package.json中eslintConfig --> airbnb
        test: /\.js$/,
        exclude: /node_modules/,
        // 優先執行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        // 以下loader只會匹配一個
        // 注意:不能有兩個配置處理同一種類型檔案
        oneOf: [
          {
            test: /\.css$/,
            use: [...commonCssLoader]
          },
          {
            test: /\.less$/,
            use: [...commonCssLoader, 'less-loader']
          },
          /*
            正常來講,一個檔案只能被一個loader處理。
            當一個檔案要被多個loader處理,那麼一定要指定loader執行的先後順序:
              先執行eslint 在執行babel
          */
          {
            test: /\.js$/,
            exclude: /node_modules/,
            use: [
              /* 
                開啟多程序打包。 
                程序啟動大概為600ms,程序通訊也有開銷。
                只有工作消耗時間比較長,才需要多程序打包
              */
              {
                loader: 'thread-loader',
                options: {
                  workers: 2 // 程序2個
                }
              },
              {
                loader: 'babel-loader',
                options: {
                  presets: [
                    [
                      '@babel/preset-env',
                      {
                        useBuiltIns: 'usage',
                        corejs: { version: 3 },
                        targets: {
                          chrome: '60',
                          firefox: '50'
                        }
                      }
                    ]
                  ],
                  // 開啟babel快取
                  // 第二次構建時,會讀取之前的快取
                  cacheDirectory: true
                }
              }
            ]
          },
          {
            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'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/built.[contenthash:10].css'
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    }),
    new WorkboxWebpackPlugin.GenerateSW({
      /*
        1. 幫助serviceworker快速啟動
        2. 刪除舊的 serviceworker

        生成一個 serviceworker 配置檔案~
      */
      clientsClaim: true,
      skipWaiting: true
    })
  ],
  mode: 'production',
  devtool: 'source-map'
};

  1. 執行指令:webpack

10 externals

  1. 建立檔案
    在這裡插入圖片描述
  2. 修改配置檔案
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    })
  ],
  mode: 'production',
  externals: {
    // 拒絕jQuery被打包進來
    jquery: 'jQuery'
  }
};
  1. 執行指令:webpack

11 dll

  1. 建立檔案
    在這裡插入圖片描述
  2. 修改配置檔案
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'built.js',
    path: resolve(__dirname, 'build')
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
    // 告訴webpack哪些庫不參與打包,同時使用時的名稱也得變~
    new webpack.DllReferencePlugin({
      manifest: resolve(__dirname, 'dll/manifest.json')
    }),
    // 將某個檔案打包輸出去,並在html中自動引入該資源
    new AddAssetHtmlWebpackPlugin({
      filepath: resolve(__dirname, 'dll/jquery.js')
    })
  ],
  mode: 'production'
};

  1. 執行指令:webpack