webpack.config.js 詳解

/*
  webpack.config.js  webpack的配置文件
    作用: 指示 webpack 干哪些活(當(dāng)你運(yùn)行 webpack 指令時(shí)哄啄,會(huì)加載里面的配置)

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

// resolve用來拼接絕對路徑的方法
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin') //壓縮
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');

/*
  緩存:
    babel緩存
      cacheDirectory: true
      --> 讓第二次打包構(gòu)建速度更快
    文件資源緩存
      hash: 每次wepack構(gòu)建時(shí)會(huì)生成一個(gè)唯一的hash值纷妆。
        問題: 因?yàn)閖s和css同時(shí)使用一個(gè)hash值焰雕。
          如果重新打包苟鸯,會(huì)導(dǎo)致所有緩存失效袱讹。(可能我卻只改動(dòng)一個(gè)文件)
      chunkhash:根據(jù)chunk生成的hash值疲扎。如果打包來源于同一個(gè)chunk,那么hash值就一樣
        問題: js和css的hash值還是一樣的
          因?yàn)閏ss是在js中被引入的椒丧,所以同屬于一個(gè)chunk
      contenthash: 根據(jù)文件的內(nèi)容生成hash值。不同文件hash值一定不一樣    
      --> 讓代碼上線運(yùn)行緩存更好使用

  tree shaking:去除無用代碼
    前提:1. 必須使用ES6模塊化  2. 開啟production環(huán)境
    作用: 減少代碼體積

    在package.json中配置 
      "sideEffects": false 所有代碼都沒有副作用(都可以進(jìn)行tree shaking)
        問題:可能會(huì)把css / @babel/polyfill (副作用)文件干掉
      "sideEffects": ["*.css", "*.less"]

  多進(jìn)程打包:thread-loader

*/

module.exports = {
  // webpack配置
  // 入口起點(diǎn)
  entry: './src/index.js',
  // 輸出
  output: {
    // 輸出文件名 [name]:取文件名
    filename: 'js/[name].[contenthash:10].js',
    // 輸出路徑
    // __dirname nodejs的變量壶熏,代表當(dāng)前文件的目錄絕對路徑
    path: resolve(__dirname, 'build')
  },
  // loader的配置
  module: {
    rules: [
      // 詳細(xì)loader配置
      // 不同文件必須配置不同loader處理
      /*
       語法檢查: eslint-loader  eslint
         注意:只檢查自己寫的源代碼句柠,第三方的庫是不用檢查的
         設(shè)置檢查規(guī)則:
           package.json中eslintConfig中設(shè)置~
             "eslintConfig": {
               "extends": "airbnb-base"
             }
           airbnb --> eslint-config-airbnb-base  eslint-plugin-import eslint
     */
      {
        test: /\.js$/,
        exclude: /node_modules/,
        // 優(yōu)先執(zhí)行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          // 自動(dòng)修復(fù)eslint的錯(cuò)誤
          fix: true
        }
      },
      {
        // 以下loader只會(huì)匹配一個(gè)
        // 注意:不能有兩個(gè)配置處理同一種類型文件
        oneOf: [
          {
            // 匹配哪些文件
            test: /\.css$/,
            // 使用哪些loader進(jìn)行處理 s
            use: [
              // use數(shù)組中l(wèi)oader執(zhí)行順序:從右到左,從下到上 依次執(zhí)行
              // 創(chuàng)建style標(biāo)簽溯职,將js中的樣式資源插入進(jìn)行帽哑,添加到head中生效
              // 'style-loader', 
              // 這個(gè)loader取代style-loader。作用:提取js中的css成單獨(dú)文件
              MiniCssExtractPlugin.loader,
              // 將css文件變成commonjs模塊加載js中僻族,里面內(nèi)容是樣式字符串
              'css-loader',
              /*
                css兼容性處理:postcss --> postcss-loader postcss-preset-env
    
                幫postcss找到package.json中browserslist里面的配置屡谐,通過配置加載指定的css兼容性樣式
    
                "browserslist": {
                  // 開發(fā)環(huán)境 --> 設(shè)置node環(huán)境變量:process.env.NODE_ENV = development
                  "development": [
                    "last 1 chrome version",
                    "last 1 firefox version",
                    "last 1 safari version"
                  ],
                  // 生產(chǎn)環(huán)境:默認(rèn)是看生產(chǎn)環(huán)境
                  "production": [
                    ">0.2%",
                    "not dead",
                    "not op_mini all"
                  ]
                }
              */
              // 使用loader的默認(rèn)配置
              // 'postcss-loader',
              // 修改loader的配置
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss',
                  plugins: () => [
                    // postcss的插件
                    require('postcss-preset-env')()
                  ]
                }
              }
            ]
          },
          {
            test: /\.less$/,
            use: [
              // 創(chuàng)建style標(biāo)簽,將樣式放入
              'style-loader',
              'css-loader',
              // 將less文件編譯成css文件
              // 需要下載 less-loader和less
              'less-loader'
            ]
          },
          {
            // 問題:默認(rèn)處理不了html中img圖片
            // 處理圖片資源
            test: /\.(jpg|png|gif)$/,
            // 使用一個(gè)loader
            // 下載 url-loader file-loader
            loader: 'url-loader',
            options: {
              // 圖片大小小于8kb度秘,就會(huì)被base64處理
              // 優(yōu)點(diǎn): 減少請求數(shù)量(減輕服務(wù)器壓力)
              // 缺點(diǎn):圖片體積會(huì)更大(文件請求速度更慢)
              limit: 8 * 1024,
              // 問題:因?yàn)閡rl-loader默認(rèn)使用es6模塊化解析剑梳,而html-loader引入圖片是commonjs
              // 解析時(shí)會(huì)出問題:[object Module]
              // 解決:關(guān)閉url-loader的es6模塊化肄梨,使用commonjs解析
              esModule: false,
              // 給圖片進(jìn)行重命名
              // [hash:10]取圖片的hash的前10位
              // [ext]取文件原來擴(kuò)展名
              name: '[hash:10].[ext]',
              // 打包到指定文件中 
              outputPath: 'imgs'
            }
          },
          {
            test: /\.html$/,
            // 處理html文件的img圖片(負(fù)責(zé)引入img,從而能被url-loader進(jìn)行處理)
            loader: 'html-loader'
          },
          // 打包其他資源(除了html/js/css資源以外的資源)
          {
            // 排除css/js/html資源
            exclude: /\.(html|js|css|less|jpg|png|gif)/,
            loader: 'file-loader',
            options: {
              name: '[hash:10].[ext]',
              outputPath: 'media'
            }
          },
          /*
             js兼容性處理:babel-loader @babel/core 
               1. 基本js兼容性處理 --> @babel/preset-env
                 問題:只能轉(zhuǎn)換基本語法侨赡,如promise高級語法不能轉(zhuǎn)換
               2. 全部js兼容性處理 --> @babel/polyfill  
                 問題:我只要解決部分兼容性問題粱侣,但是將所有兼容性代碼全部引入,體積太大了~
               3. 需要做兼容性處理的就做:按需加載  --> core-js
           */
          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              // 預(yù)設(shè):指示babel做怎么樣的兼容性處理
              presets: [
                [
                  '@babel/preset-env',
                  {
                    // 按需加載
                    useBuiltIns: 'usage',
                    // 指定core-js版本
                    corejs: {
                      version: 3
                    },
                    // 指定兼容性做到哪個(gè)版本瀏覽器
                    targets: {
                      chrome: '60',
                      firefox: '60',
                      ie: '9',
                      safari: '10',
                      edge: '17'
                    }
                  }
                ]
              ],
              // 開啟babel緩存
              // 第二次構(gòu)建時(shí)油猫,會(huì)讀取之前的緩存
              cacheDirectory: true
            }
          },
        ]
      },
    ]
  },
  // plugins的配置
  plugins: [
    // 詳細(xì)plugins的配置
    // html-webpack-plugin
    // 功能:默認(rèn)會(huì)創(chuàng)建一個(gè)空的HTML柠偶,自動(dòng)引入打包輸出的所有資源(JS/CSS)
    // 需求:需要有結(jié)構(gòu)的HTML文件
    new HtmlWebpackPlugin({
      // 復(fù)制 './src/index.html' 文件睬关,并自動(dòng)引入打包輸出的所有資源(JS/CSS)
      template: './src/index.html',
      // 壓縮html代碼
      minify: {
        // 移除空格
        collapseWhitespace: true,
        // 移除注釋
        removeComments: true
      }
    }),
    new MiniCssExtractPlugin({
      // 對輸出的css文件進(jìn)行重命名
      filename: 'css/built.[contenthash:10].css'
    }),
    // 壓縮css
    new OptimizeCssAssetsWebpackPlugin(),
    new WorkboxWebpackPlugin.GenerateSW({
      /*
        1. 幫助serviceworker快速啟動(dòng)
        2. 刪除舊的 serviceworker

        生成一個(gè) serviceworker 配置文件~
      */
      clientsClaim: true,
      skipWaiting: true
    })
  ],
  /*
  1. 可以將node_modules中代碼單獨(dú)打包一個(gè)chunk最終輸出
  2. 自動(dòng)分析多入口chunk中电爹,有沒有公共的文件料睛。如果有會(huì)打包成單獨(dú)一個(gè)chunk
*/
  optimization: {
    splitChunks: {
      chunks: 'all'
      // 默認(rèn)值,可以不寫~
      /* minSize: 30 * 1024, // 分割的chunk最小為30kb
      maxSiza: 0, // 最大沒有限制
      minChunks: 1, // 要提取的chunk最少被引用1次
      maxAsyncRequests: 5, // 按需加載時(shí)并行加載的文件的最大數(shù)量
      maxInitialRequests: 3, // 入口js文件最大并行請求數(shù)量
      automaticNameDelimiter: '~', // 名稱連接符
      name: true, // 可以使用命名規(guī)則
      cacheGroups: {
        // 分割chunk的組
        // node_modules文件會(huì)被打包到 vendors 組的chunk中屎勘。--> vendors~xxx.js
        // 滿足上面的公共規(guī)則居扒,如:大小超過30kb,至少被引用一次犀概。
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          // 優(yōu)先級
          priority: -10
        },
        default: {
          // 要提取的chunk最少被引用2次
          minChunks: 2,
          // 優(yōu)先級
          priority: -20,
          // 如果當(dāng)前要打包的模塊夜惭,和之前已經(jīng)被提取的模塊是同一個(gè)铛绰,就會(huì)復(fù)用,而不是重新打包模塊
          reuseExistingChunk: true
        } 
      }*/
    },
    // 將當(dāng)前模塊的記錄其他模塊的hash單獨(dú)打包為一個(gè)文件 runtime
    // 解決:修改a文件導(dǎo)致b文件的contenthash變化
    runtimeChunk: {
      name: entrypoint => `runtime-${entrypoint.name}`
    },
    minimizer: [
      // 配置生產(chǎn)環(huán)境的壓縮方案:js和css
      new TerserWebpackPlugin({
        // 開啟緩存
        cache: true,
        // 開啟多進(jìn)程打包
        parallel: true,
        // 啟動(dòng)source-map
        sourceMap: true
      })
    ]
  },
  externals: {
    // 拒絕jQuery被打包進(jìn)來 但是一定要在html中引用cdn 不然會(huì)報(bào)錯(cuò)
    // 參考文檔 http://events.jianshu.io/p/aaa01bb7fa78
    jquery: 'jQuery'
  },
  // 解析模塊的規(guī)則
  resolve: {
    // 配置解析模塊路徑別名: 優(yōu)點(diǎn)簡寫路徑 缺點(diǎn)路徑?jīng)]有提示
    alias: {
      $css: resolve(__dirname, 'src/css')
    },
    // 配置省略文件路徑的后綴名
    extensions: ['.js', '.json', '.jsx', '.css'],
    // 告訴 webpack 解析模塊是去找哪個(gè)目錄
    modules: [resolve(__dirname, '../../node_modules'), 'node_modules']
  },
  // 模式
  mode: 'development', // 開發(fā)模式
  // mode: 'production'


  // 開發(fā)服務(wù)器 devServer:用來自動(dòng)化(自動(dòng)編譯,自動(dòng)打開瀏覽器这嚣,自動(dòng)刷 新瀏覽器~~)
  // 特點(diǎn):只會(huì)在內(nèi)存中編譯打包,不會(huì)有任何輸出
  // 啟動(dòng)devServer指令為:npx webpack-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',
    // 除了一些基本啟動(dòng)信息以外罐旗,其他內(nèi)容都不要顯示
    quiet: true,
    // 如果出錯(cuò)了九秀,不要全屏提示~
    overlay: false,
    // 服務(wù)器代理 --> 解決開發(fā)環(huán)境跨域問題
    proxy: {
      // 一旦devServer(5000)服務(wù)器接受到 /api/xxx 的請求,就會(huì)把請求轉(zhuǎn)發(fā)到另外一個(gè)服務(wù)器(3000)
      '/api': {
        target: 'http://localhost:3000',
        // 發(fā)送請求時(shí)鼓蜒,請求路徑重寫:將 /api/xxx --> /xxx (去掉/api)
        pathRewrite: {
          '^/api': ''
        }
      }
    }
  },
}


/*
  去入口文件 添加
  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)資源暴露出去
*/
// 注冊serviceWorker
// 處理兼容性問題
// if ('serviceWorker' in navigator) {
//   window.addEventListener('load', () => {
//     navigator.serviceWorker
//       .register('/service-worker.js')
//       .then(() => {
//         console.log('sw注冊成功了~');
//       })
//       .catch(() => {
//         console.log('sw注冊失敗了~');
//       });
//   });
// }

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末锤躁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子郭计,更是在濱河造成了極大的恐慌椒振,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件庐杨,死亡現(xiàn)場離奇詭異夹供,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)哮洽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門鸟辅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人匪凉,你說我怎么就攤上這事再层。” “怎么了树绩?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵饺饭,是天一觀的道長。 經(jīng)常有香客問我瘫俊,道長悴灵,這世上最難降的妖魔是什么骂蓖? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任登下,我火速辦了婚禮,結(jié)果婚禮上被芳,老公的妹妹穿的比我還像新娘畔濒。我一直安慰自己,他們只是感情好侵状,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布趣兄。 她就那樣靜靜地躺著,像睡著了一般诽俯。 火紅的嫁衣襯著肌膚如雪承粤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天仙粱,我揣著相機(jī)與錄音彻舰,去河邊找鬼。 笑死隔心,一個(gè)胖子當(dāng)著我的面吹牛尚胞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播唯卖,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼抽减!你這毒婦竟也來了橄碾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤偎箫,失蹤者是張志新(化名)和其女友劉穎皆串,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恶复,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡谤牡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了恐疲。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片套么。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖省咨,靈堂內(nèi)的尸體忽然破棺而出玷室,到底是詐尸還是另有隱情,我是刑警寧澤穷缤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布津肛,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏芳绩。R本人自食惡果不足惜撞反,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望嘹害。 院中可真熱鬧吮便,春花似錦、人聲如沸髓需。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咧擂。三九已至,卻和暖如春云芦,著一層夾襖步出監(jiān)牢的瞬間贸桶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工堡赔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留设联,地道東北人灼捂。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像悉稠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子耀盗,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

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