webpack設置

webpack設置

檢察一切文檔頁面:
全棧開闢,獵取更多信息。

原文鏈接:第2章 設置,原文廣告模態框遮擋,瀏覽體驗不好,所以整頓成本文,輕易查找。

設置 Webpack 的體式格局有兩種:

  1. 經由過程一個 JavaScript 文件形貌設置,比方運用 webpack.config.js 文件里的設置;
  2. 實行 Webpack 可實行文件時經由過程敕令行參數傳入,比方 webpack --devtool source-map

這兩種體式格局能夠互相搭配,比方實行 Webpack 時經由過程敕令 webpack --config webpack-dev.config.js 指定設置文件,再去 webpack-dev.config.js 文件里形貌部份設置。

依據設置所影響的功用來離別,可分為:

  • Entry 設置模塊的進口;
  • Output 設置怎樣輸出終究想要的代碼;
  • Module 設置處置懲罰模塊的劃定規矩;
  • Resolve 設置尋覓模塊的劃定規矩;
  • Plugins 設置擴大插件;
  • DevServer 設置 DevServer;
  • 別的設置項 別的零星的設置項;
  • 團體設置組織 團體地形貌各設置項的組織;
  • 多種設置範例 設置文件不止能夠返回一個 Object,另有其他返回情勢;
  • 設置總結 尋覓設置 Webpack 的規律,削減頭腦累贅。

Entry

Webpack 在尋覓相對途徑的文件時會以 context 為根目次,context 默以為實行啟動 Webpack 時地點的當前事變目次。

如果想轉變 context 的默許設置,能夠在設置文件里設置:

module.exports = {
  context: path.resolve(__dirname, 'app')
}

注重, context 必需是一個絕對途徑的字符串。 除此之外,還能夠經由過程在啟動 Webpack 時帶上參數 webpack --context 來設置 context。

Chunk 稱號

Webpack 會為每一個天生的 Chunk 取一個稱號,Chunk 的稱號和 Entry 的設置有關:

  • 如果 entry 是一個 stringarray,就只會天生一個 Chunk,這時刻 Chunk 的稱號是 main
  • 如果 entry 是一個 object,就可以夠會湧現多個 Chunk,這時刻 Chunk 的稱號是 object 鍵值對里鍵的稱號。

設置動態 Entry

如果項目里有多個頁面須要為每一個頁面的進口設置一個 Entry ,但這些頁面的數目能夠會不斷增進,則這時刻 Entry 的設置會受到到其他要素的影響致使不能寫成靜態的值。其處理要領是把 Entry 設置成一個函數去動態返回上面所說的設置,代碼以下:

// 同步函數
entry: () => {
  return {
    a:'./pages/a',
    b:'./pages/b',
  }
};
// 異步函數
entry: () => {
  return new Promise((resolve)=>{
    resolve({
       a:'./pages/a',
       b:'./pages/b',
    });
  });
};

Output

output 設置怎樣輸出終究想要的代碼。output 是一個 object,內里包括一系列設置項:

filename

output.filename 設置輸出文件的稱號,為 string 範例。 如果只要一個輸出文件,則能夠把它寫成靜態穩定的:

filename: 'bundle.js'

然則在有多個 Chunk 要輸出時,就須要藉助模版和變量了。前面說到 Webpack 會為每一個 Chunk取一個稱號,能夠依據 Chunk 的稱號來辨別輸出的文件名:

filename: '[name].js'

代碼里的 [name] 代表用內置的 name 變量去替代[name],這時刻你能夠把它看做一個字符串模塊函數, 每一個要輸出的 Chunk 都邑經由過程這個函數去拼接出輸出的文件稱號。

變量名寄義
idChunk 的唯一標識,從0最先
nameChunk 的稱號
hashChunk 的唯一標識的 Hash 值
chunkhashChunk 內容的 Hash 值

个中 hashchunkhash 的長度是可指定的,[hash:8] 代表取8位 Hash 值,默許是20位。

注重 ExtractTextWebpackPlugin 插件是運用
contenthash 來代表哈希值而不是
chunkhash, 緣由在於 ExtractTextWebpackPlugin 提取出來的內容是代碼內容自身而不是由一組模塊構成的 Chunk。

chunkFilename

output.chunkFilename 設置無進口的 Chunk 在輸出時的文件稱號。 chunkFilename 和上面的 filename 異常類似,但 chunkFilename 只用於指定在運轉過程當中天生的 Chunk 在輸出時的文件稱號。 罕見的會在運轉時天生 Chunk 場景有在運用 CommonChunkPlugin、運用 import('path/to/module') 動態加載等時。 chunkFilename 支撐和 filename 一致的內置變量。

path

output.path 設置輸出文件寄存在當地的目次,必需是 string 範例的絕對途徑。平常經由過程 Node.js 的 path 模塊去獵取絕對途徑:

path: path.resolve(__dirname, 'dist_[hash]')

publicPath

在龐雜的項目里能夠會有一些構建出的資本須要異步加載,加載這些異步資本須要對應的 URL 地點。

output.publicPath 設置宣布到線上資本的 URL 前綴,為string 範例。 默許值是空字符串 '',即運用相對途徑。

把構建出的資本文件上傳到 CDN 效勞上,以利於加速頁面的翻開速率。設置代碼以下:

filename:'[name]_[chunkhash:8].js'
publicPath: 'https://cdn.example.com/assets/'

這時刻宣布到線上的 HTML 在引入 JavaScript 文件時就須要:

<script src='https://cdn.example.com/assets/a_12345678.js'></script>

運用該設置項時要警惕,稍有不慎將致使資本加載404毛病。

output.pathoutput.publicPath 都支撐字符串模版,內置變量只要一個:hash 代表一次編譯操縱的 Hash 值。

crossOriginLoading

Webpack 輸出的部份代碼塊能夠須要異步加載,而異步加載是經由過程 JSONP 體式格局完成的。 JSONP 的道理是動態地向 HTML 中插進去一個 <script src="url"></script> 標籤去加載異步資本。

output.crossOriginLoading 則是用於設置這個異步插進去的標籤的 crossorigin 值。

script 標籤的 crossorigin 屬機能夠取以下值:

  • false(默許) 在加載此劇本資本時不會帶上用戶的 Cookies;
  • use-credentials 在加載此劇本資本時會帶上用戶的 Cookies。

平常用設置 crossorigin 來獵取異步加載的劇本實行時的細緻毛病信息。

libraryTarget 和 library

當用 Webpack 去構建一個能夠被其他模塊導入運用的庫時須要用到它們。

  • output.libraryTarget 設置以何種體式格局導出庫。
  • output.library 設置導出庫的稱號。

如果設置了 output.library='LibraryName',則輸出和運用的代碼以下:

// Webpack 輸出的代碼
var LibraryName = lib_code;

// 運用庫的要領
LibraryName.doSomething();

如果 output.library 為空,則將直接輸出:lib_code

个中
lib_code 代指點出庫的代碼內容,是有返回值的一個自實行函數。

它們平常搭配在一起運用。

output.libraryTarget 是字符串的羅列範例,支撐以下設置。

var (默許)

編寫的庫將經由過程 var 被賦值給經由過程 library 指定稱號的變量。

commonjs

編寫的庫將經由過程 CommonJS2 範例導出,輸出和運用的代碼以下:

// Webpack 輸出的代碼
module.exports = lib_code;

// 運用庫的要領
require('library-name-in-npm').doSomething();

CommonJS2 和 CommonJS 範例很類似,差異在於 CommonJS 只能用
exports 導出,而 CommonJS2 在 CommonJS 的基礎上增加了
module.exports 的導出體式格局。

output.libraryTarget 為 commonjs2 時,設置 output.library 將沒有意義。

this

編寫的庫將經由過程 this 被賦值給經由過程 library 指定的稱號,輸出和運用的代碼以下:

// Webpack 輸出的代碼
this[‘LibraryName’] = lib_code;

// 運用庫的要領
this.LibraryName.doSomething();

window

編寫的庫將經由過程 window 被賦值給經由過程 library 指定的稱號,即把庫掛載到 window 上,輸出和運用的代碼以下:

// Webpack 輸出的代碼
window['LibraryName'] = lib_code;

// 運用庫的要領
window.LibraryName.doSomething();

global

編寫的庫將經由過程 global 被賦值給經由過程 library 指定的稱號,即把庫掛載到 global 上,輸出和運用的代碼以下:


// Webpack 輸出的代碼
global['LibraryName'] = lib_code;

// 運用庫的要領
global.LibraryName.doSomething();

libraryExport

output.libraryExport 設置要導出的模塊中哪些子模塊須要被導出。 它只要在 output.libraryTarget 被設置成 commonjs 或許 commonjs2 時運用才有意義。

如果要導出的模塊源代碼是:

export const a=1;
export default b=2;

現在想讓構建輸出的代碼只導出个中的 a,能夠把 output.libraryExport 設置成 a,那末構建輸出的代碼和運用要領將變成以下:

// Webpack 輸出的代碼
module.exports = lib_code['a'];

// 運用庫的要領
require('library-name-in-npm')===1;

Module

設置 Loader

rules 設置模塊的讀取和剖析劃定規矩,平常用來設置 Loader。其範例是一個數組,數組裡每一項都形貌了怎樣去處置懲罰部份文件。 設置一項 rules 時大抵經由過程以下體式格局:

  1. 前提婚配:經由過程 testincludeexclude 三個設置項來擲中 Loader 要運用劃定規矩的文件。
  2. 運用劃定規矩:對選中后的文件經由過程 use 設置項來運用 Loader,能夠只運用一個 Loader 或許依據從后往前的遞次運用一組 Loader,同時還能夠離別給 Loader 傳入參數。
  3. 重置遞次:一組 Loader 的實行遞次默許是從右到左實行,經由過程 enforce 選項能夠讓个中一個 Loader 的實行遞次放到最前或許末了。
module: {
  rules: [
    {
      // 擲中 JavaScript 文件
      test: /\.js$/,
      // 用 babel-loader 轉換 JavaScript 文件
      // ?cacheDirectory 示意傳給 babel-loader 的參數,用於緩存 babel 編譯效果加速從新編譯速率
      use: ['babel-loader?cacheDirectory'],
      // 只擲中src目次里的js文件,加速 Webpack 搜刮速率
      include: path.resolve(__dirname, 'src')
    },
    {
      // 擲中 SCSS 文件
      test: /\.scss$/,
      // 運用一組 Loader 去處置懲罰 SCSS 文件。
      // 處置懲罰遞次為從後到前,即先交給 sass-loader 處置懲罰,再把效果交給 css-loader 末了再給 style-loader。
      use: ['style-loader', 'css-loader', 'sass-loader'],
      // 消除 node_modules 目次下的文件
      exclude: path.resolve(__dirname, 'node_modules'),
    },
    {
      // 對非文本文件採納 file-loader 加載
      test: /\.(gif|png|jpe?g|eot|woff|ttf|svg|pdf)$/,
      use: ['file-loader'],
    },
  ]
}

在 Loader 須要傳入許多參數時,你還能夠經由過程一個 Object 來形貌,比方在上面的 babel-loader 設置中有以下代碼:

use: [
  {
    loader:'babel-loader',
    options:{
      cacheDirectory:true,
    },
    // enforce:'post' 的寄義是把該 Loader 的實行遞次放到末了
    // enforce 的值還能夠是 pre,代表把 Loader 的實行遞次放到最前面
    enforce:'post'
  },
  // 省略別的 Loader
]

上面的例子中 test include exclude 這三個擲中文件的設置項只傳入了一個字符串或正則,實在它們還都支撐數組範例,運用以下:

{
  test:[
    /\.jsx?$/,
    /\.tsx?$/
  ],
  include:[
    path.resolve(__dirname, 'src'),
    path.resolve(__dirname, 'tests'),
  ],
  exclude:[
    path.resolve(__dirname, 'node_modules'),
    path.resolve(__dirname, 'bower_modules'),
  ]
}

數組裡的每項之間是的關聯,即文件途徑相符數組中的任何一個前提就會被擲中。

noParse

noParse 設置項能夠讓 Webpack 疏忽對部份沒採納模塊化的文件的遞歸剖析和處置懲罰,如許做的優點是能進步構建機能。 緣由是一些庫比方 jQuery 、ChartJS 它們巨大又沒有採納模塊化規範,讓 Webpack 去剖析這些文件耗時又沒有意義。

noParse 是可選設置項,範例須如果 RegExp[RegExp]function 个中一個。

比方想要疏忽掉 jQuery 、ChartJS,能夠運用以下代碼:

// 運用正則表達式
noParse: /jquery|chartjs/

// 運用函數,從 Webpack 3.0.0 最先支撐
noParse: (content)=> {
  // content 代表一個模塊的文件途徑
  // 返回 true or false
  return /jquery|chartjs/.test(content);
}

注重被疏忽掉的文件里不應該包括
import
require
define 等模塊化語句,不然會致使構建出的代碼中包括沒法在瀏覽器環境下實行的模塊化語句。

parser

因為 Webpack 是以模塊化的 JavaScript 文件為進口,所以內置了對模塊化 JavaScript 的剖析功用,支撐 AMDCommonJSSystemJSES6

parser 屬機能夠更細粒度的設置哪些模塊語法要剖析哪些不剖析,和 noParse 設置項的區分在於 parser 能夠準確到語法層面, 而 noParse 只能控制哪些文件不被剖析。 parser 運用以下:

module: {
  rules: [
    {
      test: /\.js$/,
      use: ['babel-loader'],
      parser: {
      amd: false, // 禁用 AMD
      commonjs: false, // 禁用 CommonJS
      system: false, // 禁用 SystemJS
      harmony: false, // 禁用 ES6 import/export
      requireInclude: false, // 禁用 require.include
      requireEnsure: false, // 禁用 require.ensure
      requireContext: false, // 禁用 require.context
      browserify: false, // 禁用 browserify
      requireJs: false, // 禁用 requirejs
      }
    },
  ]
}

Resolve

Webpack 在啟動後會從設置的進口模塊動身找出一切依靠的模塊,Resolve 設置 Webpack 怎樣尋覓模塊所對應的文件。 Webpack 內置 JavaScript 模塊化語法剖析功用,默許會採納模塊化規範里約定好的劃定規矩去尋覓,但你也能夠依據本身的須要修正默許的劃定規矩。

alias

resolve.alias 設置項經由過程別號來把原導入途徑映照成一個新的導入途徑。比方運用以下設置:

// Webpack alias 設置
resolve:{
  alias:{
    components: './src/components/'
  }
}

當你經由過程 import Button from 'components/button' 導入時,現實上被 alias 等價替代成了 import Button from './src/components/button'

以上 alias 設置的寄義是把導入語句里的 components 關鍵字替代成 ./src/components/

如許做能夠會擲中太多的導入語句,alias 還支撐 $ 標記來減少局限到只擲中以關鍵字末端的導入語句:

resolve:{
  alias:{
    'react$': '/path/to/react.min.js'
  }
}

react$ 只會擲中以 react 末端的導入語句,即只會把 import 'react' 關鍵字替代成 import '/path/to/react.min.js'

mainFields

有一些第三方模塊會針對差別環境供應幾分代碼。 比方離別供應採納 ES5 和 ES6 的2份代碼,這2份代碼的位置寫在 package.json 文件里,以下:

{
  "jsnext:main": "es/index.js",// 採納 ES6 語法的代碼進口文件
  "main": "lib/index.js" // 採納 ES5 語法的代碼進口文件
}

Webpack 會依據 mainFields 的設置去決議優先採納哪份代碼,mainFields 默許以下:

mainFields: ['browser', 'main']

Webpack 會依據數組裡的遞次去 package.json 文件里尋覓,只會運用找到的第一個。

如果你想優先採納 ES6 的那份代碼,能夠如許設置:

mainFields: ['jsnext:main', 'browser', 'main']

extensions

在導入語句沒帶文件後綴時,Webpack 會自動帶上後綴後去嘗試接見文件是不是存在。 resolve.extensions 用於設置在嘗試過程當中用到的後綴列表,默許是:

extensions: ['.js', '.json']

modules

resolve.modules 設置 Webpack 去哪些目次下尋覓第三方模塊,默許是只會去 node_modules 目次下尋覓。

偶然你的項目里會有一些模塊會大批被別的模塊依靠和導入,因為別的模塊的位置散布不定,針對差別的文件都要去盤算被導入模塊文件的相對途徑, 這個途徑偶然候會很長,就像如許 import '../../../components/button' 這時刻你能夠應用 modules 設置項優化,如果那些被大批導入的模塊都在 ./src/components 目次下,把 modules 設置成:

modules:['./src/components','node_modules']

后,你能夠簡樸經由過程 import 'button' 導入。

descriptionFiles

resolve.descriptionFiles 設置形貌第三方模塊的文件稱號,也就是 package.json 文件。默許以下:

descriptionFiles: ['package.json']

enforceExtension

resolve.enforceExtension 如果設置為 true 一切導入語句都必須要帶文件後綴, 比方開啟前 import './foo' 能平常事變,開啟后就必需寫成 import './foo.js'

enforceModuleExtension

enforceModuleExtensionenforceExtension 作用類似,但 enforceModuleExtension 只對 node_modules 下的模塊見效。

enforceModuleExtension 平常搭配 enforceExtension 運用,在 enforceExtension:true 時,因為裝置的第三方模塊中大多半導入語句沒帶文件後綴, 所以這時刻經由過程設置 enforceModuleExtension:false 來兼容第三方模塊。

Plugins

Plugin 用於擴大 Webpack 功用,林林總總的 Plugin 險些讓 Webpack 能夠做任何構建相干的事變。

設置 Plugin

Plugin 的設置很簡樸,plugins 設置項接收一個數組,數組裡每一項都是一個要運用的 Plugin 的實例,Plugin 須要的參數經由過程組織函數傳入。

const CommonsChunkPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');

module.exports = {
  plugins: [
    // 一切頁面都邑用到的大眾代碼提取到 common 代碼塊中
    new CommonsChunkPlugin({
      name: 'common',
      chunks: ['a', 'b']
    }),
  ]
};

運用 Plugin 的難點在於控制 Plugin 自身供應的設置項,而不是怎樣在 Webpack 中接入 Plugin。

DevServer

要設置 DevServer ,除了在設置文件里經由過程 devServer 傳入參數外,還能夠經由過程敕令行參數傳入。 注重只要在經由過程 DevServer 去啟動 Webpack 時設置文件里 devServer 才會見效,因為這些參數所對應的功用都是 DevServer 供應的,Webpack 自身並不熟悉 devServer 設置項。

hot

devServer.hot 設置是不是啟用模塊熱替代功用。

DevServer 默許的行動是在發明源代碼被更新後會經由過程自動革新全部頁面來做到及時預覽,開啟模塊熱替代功用后將在不革新全部頁面的狀況下經由過程用新模塊替代老模塊來做到及時預覽。

inline

DevServer 的及時預覽功用依靠一個注入到頁面里的代辦客戶端去接收來自 DevServer 的敕令和擔任革新網頁的事變。

devServer.inline 用於設置是不是自動注入這個代辦客戶端到將運轉在頁面里的 Chunk 里去,默許是會自動注入。 DevServer 會依據你是不是開啟 inline 來調解它的自動革新戰略:

  • 如果開啟 inline,DevServer 會在構建完變化后的代碼時經由過程代辦客戶端控制網頁革新。
  • 如果封閉 inline,DevServer 將沒法直接控制要開闢的網頁。這時刻它會經由過程 iframe 的體式格局去運轉要開闢的網頁,當構建完變化后的代碼時經由過程革新 iframe 來完成及時預覽。

如果你想運用 DevServer 去自動革新網頁完成及時預覽,最輕易的要領是直接開啟 inline

historyApiFallback

devServer.historyApiFallback 用於輕易的開闢運用了 HTML5 History API 的單頁運用。

這類單頁運用要求效勞器在針對任何擲中的路由時都返回一個對應的 HTML 文件,比方在接見 http://localhost/userhttp://localhost/home 時都返回 index.html 文件, 瀏覽器端的 JavaScript 代碼會從 URL 里剖析出當前頁面的狀況,顯現出對應的界面。

設置 historyApiFallback 最簡樸的做法是:

historyApiFallback: true

這會致使任何要求都邑返回 index.html 文件,這隻能用於只要一個 HTML 文件的運用。

如果你的運用由多個單頁運用構成,這就須要 DevServer 依據差別的要求來返回差別的 HTML 文件,設置以下:

historyApiFallback: {
  // 運用正則婚配擲中路由
  rewrites: [
    // /user 開首的都返回 user.html
    { from: /^\/user/, to: '/user.html' },
    { from: /^\/game/, to: '/game.html' },
    // 別的的都返回 index.html
    { from: /./, to: '/index.html' },
  ]
}

contentBase

devServer.contentBase 設置 DevServer HTTP 效勞器的文件根目次。 默許狀況下為當前實行目次,平常是項目根目次,一切平常狀況下你沒必要設置它,除非你有分外的文件須要被 DevServer 效勞。 比方你想把項目根目次下的 public 目次設置成 DevServer 效勞器的文件根目次,你能夠如許設置:

devServer:{
  contentBase: path.join(__dirname, 'public')
}

這裏須要指出能夠會讓你迷惑的處所,DevServer 效勞器經由過程 HTTP 效勞暴露出的文件分為兩類:

  • 暴露當地文件。
  • 暴露 Webpack 構建出的效果,因為構建出的效果交給了 DevServer,所以你在運用了 DevServer 時在當地找不到構建出的文件。

contentBase 只能用來設置暴露當地文件的劃定規矩,你能夠經由過程 contentBase:false 來封閉暴露當地文件。

headers

devServer.headers 設置項能夠在 HTTP 相應中注入一些 HTTP 相應頭,運用以下:

devServer:{
  headers: {
    'X-foo':'bar'
  }
}

host

devServer.host 設置項用於設置 DevServer 效勞監聽的地點。

比方你想要局域網中的別的裝備接見你當地的效勞,能夠在啟動 DevServer 時帶上 --host 0.0.0.0host 的默許值是 127.0.0.1 即只要當地能夠接見 DevServer 的 HTTP 效勞。

port

devServer.port 設置項用於設置 DevServer 效勞監聽的端口,默許運用 8080 端口。 如果 8080 端口已被別的順序佔領就運用 8081,如果 8081 照樣被佔用就運用 8082,以此類推。

allowedHosts

devServer.allowedHosts 設置一個白名單列表,只要 HTTP 要求的 HOST 在列內外才平常返回,運用以下:

allowedHosts: [
  // 婚配單個域名
  'host.com',
  'sub.host.com',
  // host2.com 和一切的子域名 *.host2.com 都將婚配
  '.host2.com'
]

disableHostCheck

devServer.disableHostCheck 設置項用於設置是不是封閉用於 DNS 重綁定的 HTTP 要求的 HOST 搜檢。

DevServer 默許只接收來自當地的要求,封閉后能夠接收來自任何 HOST 的要求。 它平常用於搭配 --host 0.0.0.0 運用,因為你想要別的裝備接見你當地的效勞,但接見時是直接經由過程 IP 地點接見而不是 HOST 接見,所以須要封閉 HOST 搜檢。

https

DevServer 默許運用 HTTP 協定效勞,它也能經由過程 HTTPS 協定效勞。 有些狀況下你必需運用 HTTPS,比方 HTTP2 和 Service Worker 就必需運轉在 HTTPS 之上。 要切換成 HTTPS 效勞,最簡樸的體式格局是:

devServer:{
  https: true
}

DevServer 會自動的為你天生一份 HTTPS 證書。

如果你想用本身的證書能夠如許設置:

devServer:{
  https: {
    key: fs.readFileSync('path/to/server.key'),
    cert: fs.readFileSync('path/to/server.crt'),
    ca: fs.readFileSync('path/to/ca.pem')
  }
}

clientLogLevel

devServer.clientLogLevel 設置在客戶端的日記品級,這會影響到你在瀏覽器開闢者東西控制台里看到的日記內容。

clientLogLevel羅列範例,可取以下之一的值 none | error | warning | info。 默以為 info 級別,即輸出一切範例的日記,設置成 none 能夠不輸出任何日記。

compress

devServer.compress 設置是不是啟用 gzip 緊縮。boolean 為範例,默以為 false

open

devServer.open 用於在 DevServer 啟動且第一次構建完時自動用你體繫上默許的瀏覽器去翻開要開闢的網頁。 同時還供應 devServer.openPage 設置項用於翻開指定 URL 的網頁。

別的設置項

Target

target 設置項能夠讓 Webpack 構建出針對差別運轉環境的代碼。 target 能夠是以下之一:

target值形貌
web針對瀏覽器 (默許),一切代碼都集合在一個文件里
node針對 Node.js,運用 require 語句加載 Chunk 代碼
async-node針對 Node.js,異步加載 Chunk 代碼
webworker針對 WebWorker
electron-main針對 Electron 主線程
electron-renderer針對 Electron 襯着線程

比方當你設置 target:'node' 時,源代碼中導入 Node.js 原生模塊的語句 require('fs') 將會被保存,fs 模塊的內容不會打包進 Chunk 里。

Devtool

devtool 設置 Webpack 怎樣天生 Source Map,默許值是 false 即不天生 Source Map,想為構建出的代碼天生 Source Map 以輕易調試,能夠如許設置:

module.export = {
  devtool: 'source-map'
}

Watch 和 WatchOptions

前面引見過 Webpack 的監聽形式,它支撐監聽文件更新,在文件發作變化時從新編譯。在運用 Webpack 時監聽形式默許是封閉的,想翻開須要以下設置:

module.export = {
  watch: true
}

在運用 DevServer 時,監聽形式默許是開啟的。

除此之外,Webpack 還供應了 watchOptions 設置項去更天真的控制監聽形式,運用以下:

module.export = {
  // 只要在開啟監聽形式時,watchOptions 才有意義
  // 默以為 false,也就是不開啟
  watch: true,
  // 監聽形式運轉時的參數
  // 在開啟監聽形式時,才有意義
  watchOptions: {
    // 不監聽的文件或文件夾,支撐正則婚配
    // 默以為空
    ignored: /node_modules/,
    // 監聽到變化發作後會等300ms再去實行行動,防備文件更新太快致使從新編譯頻次太高
    // 默以為 300ms  
    aggregateTimeout: 300,
    // 推斷文件是不是發作變化是經由過程不斷的去訊問體系指定文件有無變化完成的
    // 默許每1000豪秒去問1次
    poll: 1000
  }
}

Externals

Externals 用來通知 Webpack 要構建的代碼中運用了哪些不必被打包的模塊,也就是說這些模版是外部環境供應的,Webpack 在打包時能夠疏忽它們。

有些 JavaScript 運轉環境能夠內置了一些全局變量或許模塊,比方在你的 HTML HEAD 標籤里經由過程以下代碼:

<script src="path/to/jquery.js"></script>

引入 jQuery 后,全局變量 jQuery 就會被注入到網頁的 JavaScript 運轉環境里。

如果想在運用模塊化的源代碼里導入和運用 jQuery,能夠須要如許:

import $ from 'jquery';
$('.my-element');

構建后你會發明輸出的 Chunk 里包括的 jQuery 庫的內容,這致使 jQuery 庫湧現了2次,糟蹋加載流量,最好是 Chunk 里不會包括 jQuery 庫的內容。

Externals 設置項就是為了處理這個題目。

經由過程 externals 能夠通知 Webpack JavaScript 運轉環境已內置了那些全局變量,針對這些全局變量不必打包進代碼中而是直接運用全局變量。 要處理以上題目,能夠如許設置 externals

module.export = {
  externals: {
    // 把導入語句里的 jquery 替代成運轉環境里的全局變量 jQuery
    jquery: 'jQuery'
  }
}

ResolveLoader

ResolveLoader 用來通知 Webpack 怎樣去尋覓 Loader,因為在運用 Loader 時是經由過程其包稱號去援用的, Webpack 須要依據設置的 Loader 包名去找到 Loader 的現實代碼,以挪用 Loader 去處置懲罰源文件。

ResolveLoader 的默許設置以下:

module.exports = {
  resolveLoader:{
    // 去哪一個目次下尋覓 Loader
    modules: ['node_modules'],
    // 進口文件的後綴
    extensions: ['.js', '.json'],
    // 指明進口文件位置的字段
    mainFields: ['loader', 'main']
  }
}

該設置項經常使用於加載當地的 Loader。

團體設置組織

之前的章節離別報告了每一個設置項的詳細寄義,但沒有形貌它們所處的位置和數據組織,下面經由過程一份代碼來形貌清晰:

const path = require('path');

module.exports = {
    // entry 示意 進口,Webpack 實行構建的第一步將從 Entry 最先,可籠統成輸入。
    // 範例能夠是 string | object | array
    entry: './app/entry', // 只要1個進口,進口只要1個文件
    entry: ['./app/entry1', './app/entry2'], // 只要1個進口,進口有2個文件
    entry: { // 有2個進口
        a: './app/entry-a',
        b: ['./app/entry-b1', './app/entry-b2']
    },

    // 怎樣輸出效果:在 Webpack 經由一系列處置懲罰后,怎樣輸出終究想要的代碼。
    output: {
        // 輸出文件寄存的目次,必需是 string 範例的絕對途徑。
        path: path.resolve(__dirname, 'dist'),

        // 輸出文件的稱號
        filename: 'bundle.js', // 完全的稱號
        filename: '[name].js', // 當設置了多個 entry 時,經由過程稱號模版為差別的 entry 天生差別的文件稱號
        filename: '[chunkhash].js', // 依據文件內容 hash 值天生文件稱號,用於瀏覽器長時間緩存文件

        // 宣布到線上的一切資本的 URL 前綴,string 範例
        publicPath: '/assets/', // 放到指定目次下
        publicPath: '', // 放到根目次下
        publicPath: 'https://cdn.example.com/', // 放到 CDN 上去

        // 導出庫的稱號,string 範例
        // 不填它時,默許輸出花樣是匿名的馬上實行函數
        library: 'MyLibrary',

        // 導出庫的範例,羅列範例,默許是 var
        // 能夠是 umd | umd2 | commonjs2 | commonjs | amd | this | var | assign | window | global | jsonp ,
        libraryTarget: 'umd',

        // 是不是包括有效的文件途徑信息到天生的代碼里去,boolean 範例
        pathinfo: true,

        // 附加 Chunk 的文件稱號
        chunkFilename: '[id].js',
        chunkFilename: '[chunkhash].js',

        // JSONP 異步加載資本時的回調函數稱號,須要和效勞端搭配運用
        jsonpFunction: 'myWebpackJsonp',

        // 天生的 Source Map 文件稱號
        sourceMapFilename: '[file].map',

        // 瀏覽器開闢者東西里顯現的源碼模塊稱號
        devtoolModuleFilenameTemplate: 'webpack:///[resource-path]',

        // 異步加載跨域的資本時運用的體式格局
        crossOriginLoading: 'use-credentials',
        crossOriginLoading: 'anonymous',
        crossOriginLoading: false,
    },

    // 設置模塊相干
    module: {
        rules: [ // 設置 Loader
            {
                test: /\.jsx?$/, // 正則婚配擲中要運用 Loader 的文件
                include: [ // 只會擲中這內里的文件
                    path.resolve(__dirname, 'app')
                ],
                exclude: [ // 疏忽這內里的文件
                    path.resolve(__dirname, 'app/demo-files')
                ],
                use: [ // 運用那些 Loader,有前後序次,從后往前實行
                    'style-loader', // 直接運用 Loader 的稱號
                    {
                        loader: 'css-loader',
                        options: { // 給 html-loader 傳一些參數
                        }
                    }
                ]
            },
        ],
        noParse: [ // 不必剖析和處置懲罰的模塊
            /special-library\.js$/  // 用正則婚配
        ],
    },

    // 設置插件
    plugins: [],

    // 設置尋覓模塊的劃定規矩
    resolve: {
        modules: [ // 尋覓模塊的根目次,array 範例,默許以 node_modules 為根目次
            'node_modules',
            path.resolve(__dirname, 'app')
        ],
        extensions: ['.js', '.json', '.jsx', '.css'], // 模塊的後綴名
        alias: { // 模塊別號設置,用於映照模塊
            // 把 'module' 映照 'new-module',一樣的 'module/path/file' 也會被映照成 'new-module/path/file'
            'module': 'new-module',
            // 運用末端標記 $ 后,把 'only-module' 映照成 'new-module',
            // 然則不像上面的,'module/path/file' 不會被映照成 'new-module/path/file'
            'only-module$': 'new-module',
        },
        alias: [ // alias 還支撐運用數組來更細緻的設置
            {
                name: 'module', // 老的模塊
                alias: 'new-module', // 新的模塊
                // 是不是是只映照模塊,如果是 true 只要 'module' 會被映照,如果是 false 'module/inner/path' 也會被映照
                onlyModule: true,
            }
        ],
        symlinks: true, // 是不是追隨文件軟鏈接去征采模塊的途徑
        descriptionFiles: ['package.json'], // 模塊的形貌文件
        mainFields: ['main'], // 模塊的形貌文件里的形貌進口的文件的字段稱號
        enforceExtension: false, // 是不是強迫導入語句必須要寫明文件後綴
    },

    // 輸出文件機能搜檢設置
    performance: {
        hints: 'warning', // 有機能題目時輸出正告
        hints: 'error', // 有機能題目時輸出毛病
        hints: false, // 封閉機能搜檢
        maxAssetSize: 200000, // 最大文件大小 (單元 bytes)
        maxEntrypointSize: 400000, // 最大進口文件大小 (單元 bytes)
        assetFilter: function (assetFilename) { // 過濾要搜檢的文件
            return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
        }
    },

    devtool: 'source-map', // 設置 source-map 範例

    context: __dirname, // Webpack 運用的根目次,string 範例必需是絕對途徑

    // 設置輸出代碼的運轉環境
    target: 'web', // 瀏覽器,默許
    target: 'webworker', // WebWorker
    target: 'node', // Node.js,運用 `require` 語句加載 Chunk 代碼
    target: 'async-node', // Node.js,異步加載 Chunk 代碼
    target: 'node-webkit', // nw.js
    target: 'electron-main', // electron, 主線程
    target: 'electron-renderer', // electron, 襯着線程

    externals: { // 運用來自 JavaScript 運轉環境供應的全局變量
        jquery: 'jQuery'
    },

    stats: { // 控制台輸出日記控制
        assets: true,
        colors: true,
        errors: true,
        errorDetails: true,
        hash: true,
    },

    devServer: { // DevServer 相干的設置
        proxy: { // 代辦到後端效勞接口
            '/api': 'http://localhost:3000'
        },
        contentBase: path.join(__dirname, 'public'), // 設置 DevServer HTTP 效勞器的文件根目次
        compress: true, // 是不是開啟 gzip 緊縮
        historyApiFallback: true, // 是不是開闢 HTML5 History API 網頁
        hot: true, // 是不是開啟模塊熱替代功用
        https: false, // 是不是開啟 HTTPS 形式
    },

    profile: true, // 是不是捕獲 Webpack 構建的機能信息,用於剖析什麼緣由致使構建機能不佳

    cache: false, // 是不是啟用緩存提拔構建速率

    watch: true, // 是不是最先
    watchOptions: { // 監聽形式選項
        // 不監聽的文件或文件夾,支撐正則婚配。默以為空
        ignored: /node_modules/,
        // 監聽到變化發作後會等300ms再去實行行動,防備文件更新太快致使從新編譯頻次太高
        // 默以為300ms
        aggregateTimeout: 300,
        // 推斷文件是不是發作變化是不斷的去訊問體系指定文件有無變化,默許每秒問 1000 次
        poll: 1000
    },
};

多種設置範例

除了經由過程導出一個 Object 來形貌 Webpack 所需的設置外,另有別的更天真的體式格局,以簡化差別場景的設置。

導出一個 Function

在大多半時刻你須要從統一份源代碼中構建出多份代碼,比方一份用於開闢時,一份用於宣布到線上。

如果採納導出一個 Object 來形貌 Webpack 所需的設置的要領,須要寫兩個文件。 一個用於開闢環境,一個用於線上環境。再在啟動時經由過程 webpack --config webpack.config.js 指定運用哪一個設置文件。

採納導出一個 Function 的體式格局,能經由過程 JavaScript 天真的控制設置,做到只寫一個設置文件就可以完成以上要求。

導出一個 Function 的運用體式格局以下:

const path = require('path');
const UglifyJsPlugin = require('webpack/lib/optimize/UglifyJsPlugin');

module.exports = function (env = {}, argv) {
    const plugins = [];

    const isProduction = env['production'];

    // 在天生環境才緊縮
    if (isProduction) {
        plugins.push(
            // 緊縮輸出的 JS 代碼
            new UglifyJsPlugin()
        )
    }

    return {
        plugins: plugins,
        // 在天生環境不輸出 Source Map
        devtool: isProduction ? undefined : 'source-map',
    };
};

在運轉 Webpack 時,會給這個函數傳入2個參數,離別是:

  1. env:當前運轉時的 Webpack 專屬環境變量,env 是一個 Object。讀取時直接接見 Object 的屬性,設置它須要在啟動 Webpack 時帶上參數。比方啟動敕令是 webpack --env.production --env.bao=foo 時,則 env 的值是 {"production":"true","bao":"foo"}
  2. argv:代表在啟動 Webpack 時一切經由過程敕令行傳入的參數,比方 --config、--env、--devtool,能夠經由過程 webpack -h 列出一切 Webpack 支撐的敕令行參數。

就以上設置文件而言,在開闢時實行敕令 webpack 構建出輕易調試的代碼,在須要構建出宣布到線上的代碼時實行 webpack --env.production 構建出緊縮的代碼。

導出一個返回 Promise 的函數

在有些狀況下你不能以同步的體式格局返回一個形貌設置的 Object,Webpack 還支撐導出一個返回 Promise 的函數,運用以下:

module.exports = function(env = {}, argv) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        // ...
      })
    }, 5000)
  })
}

導出多份設置

除了只導出一份設置外,Webpack 還支撐導出一個數組,數組中能夠包括每份設置,而且每份設置都邑實行一遍構建。

運用以下:

module.exports = [
  // 採納 Object 形貌的一份設置
  {
    // ...
  },
  // 採納函數形貌的一份設置
  function() {
    return {
      // ...
    }
  },
  // 採納異步函數形貌的一份設置
  function() {
    return Promise();
  }
]

以上設置會致使 Webpack 針對這三份設置實行三次差別的構建。

這迥殊適合於用 Webpack 構建一個要上傳到 Npm 堆棧的庫,因為庫中能夠須要包括多種模塊化花樣的代碼,比方 CommonJS、UMD。

設置總結

夙昔面的設置看來選項許多,Webpack 內置了許多功用。

你沒必要都記着它們,只須要也許邃曉 Webpack 道理和中心觀點去推斷選項大抵屬於哪一個大模塊下,再去查細緻的運用文檔。

平常你可用以下履歷去推斷怎樣設置 Webpack:

  • 想讓源文件加入到構建流程中去被 Webpack 控制,設置 entry
  • 想自定義輸出文件的位置和稱號,設置 output
  • 想自定義尋覓依靠模塊時的戰略,設置 resolve
  • 想自定義剖析和轉換文件的戰略,設置 module,平常是設置 module.rules 里的 Loader。
  • 別的的大部份需求能夠要經由過程 Plugin 去完成,設置 plugin
    原文作者:whjin
    原文地址: https://segmentfault.com/a/1190000014982619
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞