第7章:生產環境配置

環境變量

經過DefinePlugin配置環境變量javascript

new webpack.DefinePlugin({
    ENV:JSON.stringify('production'),
    ENV_ID:1234,
    CONSTANTS:JSON.stringify({TYPES:['foo','bar']})
})

注意:咱們在一些值外面加上了JSON.stringify,這是由於DefinePlugin在替換環境變量時對於字符串是直接替換,若是不加JSON.stringify,在替換後就會變成變量名,而非字符串。所以對於字符串環境變量及包含字符串的對象都要加上JSON.stringify才行
設置mode能夠默認定義process.env.NODE\_ENVDE的值css

source map

原理

webpack對於工程源碼的每一步處理均可能會改變代碼的位置,結構甚至是所處文件。因此咱們生成map文件,方便咱們在調試時尋找代碼源頭。他是源碼的映射,能夠將壓縮後的代碼再對應回未壓縮的源碼。使得咱們在調試線上產品時,就好像在調試開發環境的代碼。文件默認就是打包後的文件名加上.map,如bundle.js.map。
在生成map文件的同時,bundle文件中會追加一行註釋來標註map文件的位置。如:html

//bundle.js
(function(){
//bundle的內容
})();
//# sourceMappingURL=bundle.js.map

設置sourcemap

module.exports = {
//...
devtool:'source-map'
}

對於css,scss,less來講須要添加額外的source map配置項java

loaders: {
    css: {
      options:{
        sourceMap: true
      }
    },
    less:{
      options:{
        javascriptEnabled: true,
        sourceMap: true
      }
    }
  }

資源壓縮

壓縮js

webpack4中默認使用terser的插件terser-webpack-plugin壓縮jsjquery

開啓壓縮

1手動配置webpack

module.exports = {
//...
optimization:{
    minimize:true
}
}

2 生產環境默認配置
設置mode爲production後webpack也會默認開啓壓縮web

壓縮css

壓縮css的前提時使用mini-css-extract-plugin將樣式提取出來。而後手動配置以下代碼緩存

//...
{ loader: 'css-loader', options: { sourceMap: true } }

資源緩存

hash、chunkhash、contenthash服務器

hash通常是結合CDN緩存來使用,經過webpack構建以後,生成對應文件名自動帶上對應的MD5值。若是文件內容改變的話,那麼對應文件哈希值也會改變,對應的HTML引用的URL地址也會改變,觸發CDN服務器從源服務器上拉取對應數據,進而更新本地緩存。可是在實際使用的時候,這幾種hash計算仍是有必定區別。
咱們先建一個測試案例來模擬下:app

項目結構

咱們的項目結構很簡單,入口文件index.js,引用了index.css。而後新建了jquery.js和test.js做爲公共庫。

//index.js

 require('./index.css')
 module.exports = function(){
  console.log(`I'm jack`)
  var a = 12
 }
//index.css

 .selected : {
   display: flex;
   transition: all .6s;
   user-select: none;
   background: linear-gradient(to bottom, white, black);
 }

接着咱們修改webpack.config.js來模擬不一樣hash計算

hash

hash是跟整個項目的構建相關,只要項目裏有文件更改,整個項目構建的hash值都會更改,而且所有文件都共用相同的hash值

var extractTextPlugin = require('extract-text-webpack-plugin'),
  path = require('path')
 
 module.exports = {
  context : path.join(__dirname,'src'),
  entry:{
  main: './index.js',
  vender:['./jquery.js','./test.js']
  },
  module:{
  rules:[{
   test:/\.css$/,
   use: extractTextPlugin.extract({
   fallback:'style-loader',
   use:'css-loader'
   })
  }]
  },
  output:{
  path:path.join(__dirname, '/dist/js'),
  filename: 'bundle.[name].[hash].js',
  },
  plugins:[
  new extractTextPlugin('../css/bundle.[name].[hash].css')
  ]
 }

根據上面的配置,咱們執行webpack命令以後,能夠獲得下面的結果

採用hash計算的執行結果1:

執行結果2:

咱們能夠看到構建生成的文件hash值都是同樣的,因此hash計算是跟整個項目的構建相關,同一次構建過程當中生成的哈希都是同樣的

**chunkhash
**

採用hash計算的話,每一次構建後生成的哈希值都不同,即便文件內容壓根沒有改變。這樣子是沒辦法實現緩存效果,咱們須要換另外一種哈希值計算方式,即chunkhash。

chunkhash和hash不同,它根據不一樣的入口文件(Entry)進行依賴文件解析、構建對應的chunk,生成對應的哈希值。咱們在生產環境裏把一些公共庫和程序入口文件區分開,單獨打包構建,接着咱們採用chunkhash的方式生成哈希值,那麼只要咱們不改動公共庫的代碼,就能夠保證其哈希值不會受影響。

var extractTextPlugin = require('extract-text-webpack-plugin'),
  path = require('path')
 
 module.exports = {
  ...
  ...
  output:{
  path:path.join(__dirname, '/dist/js'),
  filename: 'bundle.[name].[chunkhash].js',
  },
  plugins:[
  new extractTextPlugin('../css/bundle.[name].[chunkhash].css')
  ]
 }

採用chunkhash計算的執行結果1:

執行結果2:

咱們能夠看到,因爲採用chunkhash,因此項目主入口文件Index.js及其對應的依賴文件Index.css因爲被打包在同一個模塊,因此共用相同的chunkhash,可是公共庫因爲是不一樣的模塊,因此有單獨的chunkhash。這樣子就保證了在線上構建的時候只要文件內容沒有更改就不會重複構建

contenthash

在chunkhash的例子,咱們能夠看到因爲index.css被index.js引用了,因此共用相同的chunkhash值。可是這樣子有個問題,若是index.js更改了代碼,css文件就算內容沒有任何改變,因爲是該模塊發生了改變,致使css文件會重複構建。
這個時候,咱們能夠使用extra-text-webpack-plugin裏的contenthash值,保證即便css文件所處的模塊裏就算其餘文件內容改變,只要css文件內容不變,那麼不會重複構建。

var extractTextPlugin = require('extract-text-webpack-plugin'),
  path = require('path')
 
 module.exports = {
  ...
  ...
  output:{
  path:path.join(__dirname, '/dist/js'),
  filename: 'bundle.[name].[chunkhash].js',
  },
  plugins:[
  new extractTextPlugin('../css/bundle.[name].[contenthash].css')
  ]
 }

採用contenthash計算的執行結果1:

執行結果2:

html-webpack-plugin

//webpack.config.js 
const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  entry: {
    home: path.resolve(__dirname, './src/app.js')
  },
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js'
  },
  plugins: [
    new htmlWebpackPlugin({
        template: './src/index.html'//能夠指定html模板,方便咱們放入個性化內容。它就會以該html生成一個一摸同樣的html文件,而後自動塞入打包後的資源。固然也能夠不指定模板。
    })
  ]
}
相關文章
相關標籤/搜索