webpack優化配置

一 HMR

1. webpack.config.js

const {resolve} = require('path')
const htmlPlugin = require('html-webpack-plugin')
const cssPlugin = require('mini-css-extract-plugin')
const cssCompress = require('optimize-css-assets-webpack-plugin')

/*
* HMR: hot module replacement 熱模塊替換
* 樣式文件:可以使用HMR,因爲style-loader內部實現了
* JS文件:默認不使用HMR,需要修改入口文件JS代碼來監聽其他JS文件的變化
*   且入口文件沒有HMR功能,當入口文件改變,所有文件會被重新編譯
* html文件:當開啓HMR功能後,html文件改變不會進行重新編譯
*   需在entry中加入html文件
*
* */

//設置nodejs環境變量
process.env.NODE_ENV = 'development'

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'js/build.js',
    path: resolve(__dirname, 'build')
  },
  module: {

    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
//優先執行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        oneOf: [
          {
            test: /\.less$/,
            use: ['style-loader', 'css-loader', 'less-loader']
          },
          {
            test: /\.css$/,
            use: [cssPlugin.loader,
              'css-loader',
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss',
                  plugins: () => [
                    require('postcss-preset-env')()
                  ]
                }
              }
            ]
          },
          {
            test: /\.(jpg|png|gif)$/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              esModule: false,
              outputPath: 'imgs'
            }
          },
          {
            test: /\.html$/,
            loader: 'html-loader',
          },
          {
            exclude: /\.(html|js|css|less|png|jpg|gif)$/,
            loader: 'file-loader',
            options: {
              name: '[hash:10].[ext]',
              outputPath: 'media'
            }
          },

          {
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/,
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: {
                      version: 3
                    },
                    targets: {
                      chrome: '60',
                      firefox: '60',
                      ie: '9',
                      safari: '10',
                      edge: '17'
                    }
                  }
                ]
              ]
            }
          }
        ]
      }

    ]
  },
  plugins: [
    new htmlPlugin({
      template: "./src/index.html",
//html壓縮
      minify: {
        collapseWhitespace: true, //移除空格
        removeComments: true      //移除註釋
      }
    }),
    new cssPlugin({
      filename: 'css/build.css'
    }),
    new cssCompress()
  ],
//生產環境下自動壓縮js代碼
  mode: 'production',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    port: 3000,
    open: true,
    hot: true,
    devtool: 'source-map'
  }
}



2. index.js

import './base.less';
import './index.css';

if(module.hot){ //module.hot爲true說明開啓了HMR功能
  module.hot.accept('./print.js', function(){
    //監聽print.js文件的變化 一旦發生變化,其他模塊不會重新打包,且執行後面的回調函數
    print()
  })
}

二 source-map

const {resolve} = require('path')
const htmlPlugin = require('html-webpack-plugin')
const cssPlugin = require('mini-css-extract-plugin')
const cssCompress = require('optimize-css-assets-webpack-plugin')

/*
* source-map 一種提供源代碼到構建後代碼映射技術,如果構建後代碼出錯了,通過映射可以追蹤源代碼錯誤的語句)
* source-map 外部
*   錯誤代碼原因 和 源代碼的錯誤位置
* hidden-source-map 外部
*   錯誤代碼原因 和 不能追蹤源代碼的錯誤位置,只提示構建後代碼的錯誤位置
* nosources-source-map 外部
*   錯誤代碼原因 但沒有任何源代碼信息
* cheap-source-map 外部
*   錯誤代碼原因 和 源代碼的錯誤位置 精確到行
* cheap-module-source-map 外部
*   錯誤代碼原因 和 源代碼的錯誤位置
*   module會將loader的source map 加入
* inline-source-map 內聯
*   只生成一個內斂source-map
*   錯誤代碼原因 和 源代碼的錯誤位置
* eval-source-map 內聯
*   每個文件生成對面source-map,都在eval函數裏
*   錯誤代碼準確信息 和 源代碼的錯誤位置
*
*   內聯和外部的區別:1.外部生成了文件,內聯沒有 2.內聯構建速度更快
*
* 開發環境建議用 eval-source-map / eval-cheap-module-source-map
* 生產環境建議用 source-map / cheap-module-source-map
*   如果要隱藏代碼可以用 nosources-source-map / hidden-source-map
* * */

//設置nodejs環境變量
process.env.NODE_ENV = 'development'

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'js/build.js',
    path: resolve(__dirname, 'build')
  },
  module: {

    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
//優先執行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        oneOf: [
          {
            test: /\.less$/,
            use: ['style-loader', 'css-loader', 'less-loader']
          },
          {
            test: /\.css$/,
            use: [cssPlugin.loader,
              'css-loader',
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss',
                  plugins: () => [
                    require('postcss-preset-env')()
                  ]
                }
              }
            ]
          },
          {
            test: /\.(jpg|png|gif)$/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              esModule: false,
              outputPath: 'imgs'
            }
          },
          {
            test: /\.html$/,
            loader: 'html-loader',
          },
          {
            exclude: /\.(html|js|css|less|png|jpg|gif)$/,
            loader: 'file-loader',
            options: {
              name: '[hash:10].[ext]',
              outputPath: 'media'
            }
          },

          {
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/,
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: {
                      version: 3
                    },
                    targets: {
                      chrome: '60',
                      firefox: '60',
                      ie: '9',
                      safari: '10',
                      edge: '17'
                    }
                  }
                ]
              ]
            }
          }
        ]
      }

    ]
  },
  plugins: [
    new htmlPlugin({
      template: "./src/index.html",
//html壓縮
      minify: {
        collapseWhitespace: true, //移除空格
        removeComments: true      //移除註釋
      }
    }),
    new cssPlugin({
      filename: 'css/build.css'
    }),
    new cssCompress()
  ],
//生產環境下自動壓縮js代碼
  mode: 'production',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    port: 3000,
    open: true,
    hot: true,
    devtool: 'source-map'
  }
}



三 oneOf

const {resolve} = require('path')
const htmlPlugin = require('html-webpack-plugin')
const cssPlugin = require('mini-css-extract-plugin')
const cssCompress = require('optimize-css-assets-webpack-plugin')

//設置nodejs環境變量
process.env.NODE_ENV = 'development'

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'js/build.js',
    path: resolve(__dirname, 'build')
  },
  module: {

    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
//優先執行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        //oneOf: 若多個配置有用到相同的loader,則只加載一個,減少資源消耗
        //但是oneOf中不能有兩個配置處理同一種類型文件
        oneOf: [
          {
            test: /\.less$/,
            use: ['style-loader', 'css-loader', 'less-loader']
          },
          {
            test: /\.css$/,
            use: [cssPlugin.loader,
              'css-loader',
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss',
                  plugins: () => [
                    require('postcss-preset-env')()
                  ]
                }
              }
            ]
          },
          {
            test: /\.(jpg|png|gif)$/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              esModule: false,
              outputPath: 'imgs'
            }
          },
          {
            test: /\.html$/,
            loader: 'html-loader',
          },
          {
            exclude: /\.(html|js|css|less|png|jpg|gif)$/,
            loader: 'file-loader',
            options: {
              name: '[hash:10].[ext]',
              outputPath: 'media'
            }
          },

          {
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/,
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: {
                      version: 3
                    },
                    targets: {
                      chrome: '60',
                      firefox: '60',
                      ie: '9',
                      safari: '10',
                      edge: '17'
                    }
                  }
                ]
              ]
            }
          }
        ]
      }

    ]
  },
  plugins: [
    new htmlPlugin({
      template: "./src/index.html",
//html壓縮
      minify: {
        collapseWhitespace: true, //移除空格
        removeComments: true      //移除註釋
      }
    }),
    new cssPlugin({
      filename: 'css/build.css'
    }),
    new cssCompress()
  ],
//生產環境下自動壓縮js代碼
  mode: 'production',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    port: 3000,
    open: true,
    hot: true,
    devtool: 'source-map'
  }
}

四 緩存

const {resolve} = require('path')
const htmlPlugin = require('html-webpack-plugin')
const cssPlugin = require('mini-css-extract-plugin')
const cssCompress = require('optimize-css-assets-webpack-plugin')

/*
* babel緩存 文件再次編譯的時候會優先從緩存中取
*   cacheDirectory: true
* 文件資源緩存
*   hash: 每次webpack構建時會生成一個唯一的hash值
*     問題:js和css會同時使用同一個hash值,當只改變一個文件時,重新打包會使緩存失效
*   chunkhash:根據chunk生成的hash值,如果打包來源於同一個chunk,那麼hash值就一樣
*     問題:js和css的值還是一樣的,因爲css是在js中被引入的,所以同屬於一個chunk
*   contenthash:根據文件內容生成hash值,不同文件hash值一定不一樣
* */

//設置nodejs環境變量
process.env.NODE_ENV = 'development'

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'js/build.[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
//優先執行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        oneOf: [
          {
            test: /\.less$/,
            use: ['style-loader', 'css-loader', 'less-loader']
          },
          {
            test: /\.css$/,
            use: [cssPlugin.loader,
              'css-loader',
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss',
                  plugins: () => [
                    require('postcss-preset-env')()
                  ]
                }
              }
            ]
          },
          {
            test: /\.(jpg|png|gif)$/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              esModule: false,
              outputPath: 'imgs'
            }
          },
          {
            test: /\.html$/,
            loader: 'html-loader',
          },
          {
            exclude: /\.(html|js|css|less|png|jpg|gif)$/,
            loader: 'file-loader',
            options: {
              name: '[hash:10].[ext]',
              outputPath: 'media'
            }
          },

          {
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/,
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: {
                      version: 3
                    },
                    targets: {
                      chrome: '60',
                      firefox: '60',
                      ie: '9',
                      safari: '10',
                      edge: '17'
                    }
                  }
                ]
              ],
              cacheDirectory: true
            }
          }
        ]
      }

    ]
  },
  plugins: [
    new htmlPlugin({
      template: "./src/index.html",
//html壓縮
      minify: {
        collapseWhitespace: true, //移除空格
        removeComments: true      //移除註釋
      }
    }),
    new cssPlugin({
      filename: 'css/build.[contenthash:10].css'
    }),
    new cssCompress()
  ],
//生產環境下自動壓縮js代碼
  mode: 'production',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    port: 3000,
    open: true,
    hot: true,
    devtool: 'source-map'
  }
}

五 tree shaking

1. webpack.config.js配置

const {resolve} = require('path')
const htmlPlugin = require('html-webpack-plugin')
const cssPlugin = require('mini-css-extract-plugin')
const cssCompress = require('optimize-css-assets-webpack-plugin')

/*
* tree shaking: 去除無用代碼
*   前提:1. 使用es6模塊化 2.開啓production環境
* package.json中的配置
*   "sideEffects": false 所有代碼沒有副作用
*     問題:可能會把css等直接引入但在js文件中沒有使用的文件給抹去
*   "sideEffects": ["*.css"]    //css不被優化
* */

//設置nodejs環境變量
process.env.NODE_ENV = 'development'

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'js/build.[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
//優先執行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        oneOf: [
          {
            test: /\.less$/,
            use: ['style-loader', 'css-loader', 'less-loader']
          },
          {
            test: /\.css$/,
            use: [cssPlugin.loader,
              'css-loader',
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss',
                  plugins: () => [
                    require('postcss-preset-env')()
                  ]
                }
              }
            ]
          },
          {
            test: /\.(jpg|png|gif)$/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              esModule: false,
              outputPath: 'imgs'
            }
          },
          {
            test: /\.html$/,
            loader: 'html-loader',
          },
          {
            exclude: /\.(html|js|css|less|png|jpg|gif)$/,
            loader: 'file-loader',
            options: {
              name: '[hash:10].[ext]',
              outputPath: 'media'
            }
          },
          {
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/,
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: {
                      version: 3
                    },
                    targets: {
                      chrome: '60',
                      firefox: '60',
                      ie: '9',
                      safari: '10',
                      edge: '17'
                    }
                  }
                ]
              ],
              cacheDirectory: true
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new htmlPlugin({
      template: "./src/index.html",
//html壓縮
      minify: {
        collapseWhitespace: true, //移除空格
        removeComments: true      //移除註釋
      }
    }),
    new cssPlugin({
      filename: 'css/build.[contenthash:10].css'
    }),
    new cssCompress()
  ],
//生產環境下自動壓縮js代碼
  mode: 'production',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    port: 3000,
    open: true,
    hot: true,
    devtool: 'source-map'
  }
}

2. package.json配置

{
  "name": "web-pack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.8.7",
    "@babel/preset-env": "^7.8.7",
    "babel-loader": "^8.0.6",
    "core-js": "^3.6.4",
    "css-loader": "^3.4.2",
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.1.0",
    "eslint-loader": "^3.0.3",
    "eslint-plugin-import": "^2.20.1",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.11.1",
    "less-loader": "^5.0.0",
    "mini-css-extract-plugin": "^0.9.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^3.0.0",
    "postcss-preset-env": "^6.7.0",
    "style-loader": "^1.1.3",
    "webpack": "^4.42.0",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3"
  },
  "dependencies": {
    "file-loader": "^6.0.0",
    "html-loader": "^0.5.5",
    "url-loader": "^4.0.0"
  },
  "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
  "eslintConfig": {
    "extends": "airbnb-base"
  },
  "sideEffects": ["*.css"]
}

六 PWA

1. 安裝workbox-webpack-plugin

npm i workbox-webpack-plugin -D

2. webpack.config.js

const {resolve} = require('path')
const htmlPlugin = require('html-webpack-plugin')
const cssPlugin = require('mini-css-extract-plugin')
const cssCompress = require('optimize-css-assets-webpack-plugin')
const workBox = require('workbox-webpack-plugin')

//設置nodejs環境變量
process.env.NODE_ENV = 'development'

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'js/build.[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
//優先執行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        oneOf: [
          {
            test: /\.less$/,
            use: ['style-loader', 'css-loader', 'less-loader']
          },
          {
            test: /\.css$/,
            use: [cssPlugin.loader,
              'css-loader',
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss',
                  plugins: () => [
                    require('postcss-preset-env')()
                  ]
                }
              }
            ]
          },
          {
            test: /\.(jpg|png|gif)$/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              esModule: false,
              outputPath: 'imgs'
            }
          },
          {
            test: /\.html$/,
            loader: 'html-loader',
          },
          {
            exclude: /\.(html|js|css|less|png|jpg|gif)$/,
            loader: 'file-loader',
            options: {
              name: '[hash:10].[ext]',
              outputPath: 'media'
            }
          },
          {
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/,
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: {
                      version: 3
                    },
                    targets: {
                      chrome: '60',
                      firefox: '60',
                      ie: '9',
                      safari: '10',
                      edge: '17'
                    }
                  }
                ]
              ],
              cacheDirectory: true
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new htmlPlugin({
      template: "./src/index.html",
//html壓縮
      minify: {
        collapseWhitespace: true, //移除空格
        removeComments: true      //移除註釋
      }
    }),
    new cssPlugin({
      filename: 'css/build.[contenthash:10].css'
    }),
    new cssCompress(),
    new workBox.GenerateSW({
      /*
      * 1. 幫助serviceworker快速啓動
      * 2. 刪除舊的 serviceworker
      * */
      clientsClaim: true,
      skipWaiting: true
    })
  ],
//生產環境下自動壓縮js代碼
  mode: 'production',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    port: 3000,
    open: true,
    hot: true,
    devtool: 'source-map'
  }
}

3. index.js

import './base.less';
import './index.css';

/* 1. eslint不認識 window navigator全局變量
      解決:在package.json中eslintConfig配置
   2. sw代碼必須運行在服務器上
      npm i serve -g
      serve -s build 啓動服務器,將build目錄下所有資源作爲靜態資源暴露出去
*/
// 註冊 serviceWorker 處理兼容性問題
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker
      .register('/service-worker.js')
      .then(() => {
        console.log('註冊成功');
      })
      .catch(() => {
        console.log('註冊失敗');
      });
  });
}

4. package.json

{
  "name": "web-pack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.8.7",
    "@babel/preset-env": "^7.8.7",
    "babel-loader": "^8.0.6",
    "core-js": "^3.6.4",
    "css-loader": "^3.4.2",
    "eslint": "^6.8.0",
    "eslint-config-airbnb-base": "^14.1.0",
    "eslint-loader": "^3.0.3",
    "eslint-plugin-import": "^2.20.1",
    "html-webpack-plugin": "^3.2.0",
    "less": "^3.11.1",
    "less-loader": "^5.0.0",
    "mini-css-extract-plugin": "^0.9.0",
    "optimize-css-assets-webpack-plugin": "^5.0.3",
    "postcss-loader": "^3.0.0",
    "postcss-preset-env": "^6.7.0",
    "style-loader": "^1.1.3",
    "webpack": "^4.42.0",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3",
    "workbox-webpack-plugin": "^5.1.1"
  },
  "dependencies": {
    "file-loader": "^6.0.0",
    "html-loader": "^0.5.5",
    "url-loader": "^4.0.0"
  },
  "browserslist": {
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ],
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ]
  },
  "eslintConfig": {
    "extends": "airbnb-base",
    "env": {
      "browser": true
    }
  },
  "sideEffects": [
    "*.css"
  ]
}

七 多進程打包

1. 安裝thread-loader

npm i thread-loader -D

2. 配置

const {resolve} = require('path')
const htmlPlugin = require('html-webpack-plugin')
const cssPlugin = require('mini-css-extract-plugin')
const cssCompress = require('optimize-css-assets-webpack-plugin')
const workBox = require('workbox-webpack-plugin')


//設置nodejs環境變量
process.env.NODE_ENV = 'development'

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'js/build.[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
//優先執行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        oneOf: [
          {
            test: /\.less$/,
            use: ['style-loader', 'css-loader', 'less-loader']
          },
          {
            test: /\.css$/,
            use: [cssPlugin.loader,
              'css-loader',
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss',
                  plugins: () => [
                    require('postcss-preset-env')()
                  ]
                }
              }
            ]
          },
          {
            test: /\.(jpg|png|gif)$/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              esModule: false,
              outputPath: 'imgs'
            }
          },
          {
            test: /\.html$/,
            loader: 'html-loader',
          },
          {
            exclude: /\.(html|js|css|less|png|jpg|gif)$/,
            loader: 'file-loader',
            options: {
              name: '[hash:10].[ext]',
              outputPath: 'media'
            }
          },
          {
            test: /\.js$/,
            exclude: /node_modules/,
            /*開啓多進程打包,但是要注意,一般給打包時間很長的過程才啓用多線程
            * 因爲啓動進程大概600ms,進程通信也要開銷*/
            use:[
              'thread-loader',
              {
                loader: 'babel-loader',
                options: {
                  presets: [
                    [
                      '@babel/preset-env',
                      {
                        useBuiltIns: 'usage',
                        corejs: {
                          version: 3
                        },
                        targets: {
                          chrome: '60',
                          firefox: '60',
                          ie: '9',
                          safari: '10',
                          edge: '17'
                        }
                      }
                    ]
                  ],
                  cacheDirectory: true
                }
              }
            ],
          }
        ]
      }
    ]
  },
  plugins: [
    new htmlPlugin({
      template: "./src/index.html",
//html壓縮
      minify: {
        collapseWhitespace: true, //移除空格
        removeComments: true      //移除註釋
      }
    }),
    new cssPlugin({
      filename: 'css/build.[contenthash:10].css'
    }),
    new cssCompress(),
    new workBox.GenerateSW({
      clientsClaim: true,
      skipWaiting: true
    })
  ],
//生產環境下自動壓縮js代碼
  mode: 'production',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    port: 3000,
    open: true,
    hot: true,
    devtool: 'source-map'
  }
}

八 externals

const {resolve} = require('path')
const htmlPlugin = require('html-webpack-plugin')
const cssPlugin = require('mini-css-extract-plugin')
const cssCompress = require('optimize-css-assets-webpack-plugin')
const workBox = require('workbox-webpack-plugin')


//設置nodejs環境變量
process.env.NODE_ENV = 'development'

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'js/build.[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
//優先執行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true
        }
      },
      {
        oneOf: [
          {
            test: /\.less$/,
            use: ['style-loader', 'css-loader', 'less-loader']
          },
          {
            test: /\.css$/,
            use: [cssPlugin.loader,
              'css-loader',
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss',
                  plugins: () => [
                    require('postcss-preset-env')()
                  ]
                }
              }
            ]
          },
          {
            test: /\.(jpg|png|gif)$/,
            loader: 'url-loader',
            options: {
              limit: 8 * 1024,
              name: '[hash:10].[ext]',
              esModule: false,
              outputPath: 'imgs'
            }
          },
          {
            test: /\.html$/,
            loader: 'html-loader',
          },
          {
            exclude: /\.(html|js|css|less|png|jpg|gif)$/,
            loader: 'file-loader',
            options: {
              name: '[hash:10].[ext]',
              outputPath: 'media'
            }
          },
          {
            test: /\.js$/,
            exclude: /node_modules/,
            /*開啓多進程打包,但是要注意,一般給打包時間很長的過程才啓用多線程
            * 因爲啓動進程大概600ms,進程通信也要開銷*/
            use:[
              'thread-loader',
              {
                loader: 'babel-loader',
                options: {
                  presets: [
                    [
                      '@babel/preset-env',
                      {
                        useBuiltIns: 'usage',
                        corejs: {
                          version: 3
                        },
                        targets: {
                          chrome: '60',
                          firefox: '60',
                          ie: '9',
                          safari: '10',
                          edge: '17'
                        }
                      }
                    ]
                  ],
                  cacheDirectory: true
                }
              }
            ],
          }
        ]
      }
    ]
  },
  plugins: [
    new htmlPlugin({
      template: "./src/index.html",
//html壓縮
      minify: {
        collapseWhitespace: true, //移除空格
        removeComments: true      //移除註釋
      }
    }),
    new cssPlugin({
      filename: 'css/build.[contenthash:10].css'
    }),
    new cssCompress(),
    new workBox.GenerateSW({
      clientsClaim: true,
      skipWaiting: true
    })
  ],
//生產環境下自動壓縮js代碼
  mode: 'production',
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    compress: true,
    port: 3000,
    open: true,
    hot: true,
    devtool: 'source-map'
  },
  externals: {
//拒絕jQuery被打包進來 但是需要手動在html文件中進行引入
    jquery: 'jQuery'
  }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章