webpack 對Externals的說明
外部擴展(Externals)
externals 配置選項提供了「從輸出的 bundle 中排除依賴」的方法。相反,所創(chuàng)建的 bundle 依賴于那些存在于用戶環(huán)境(consumer's environment)中的依賴。此功能通常對 library 開發(fā)人員來說是最有用的,然而也會有各種各樣的應用程序用到它。
externals
string [string] object function RegExp
防止將某些 import 的包(package)打包到 bundle 中,而是在運行時(runtime)再去從外部獲取這些擴展依賴(external dependencies)。
例如,從 CDN 引入 jQuery,而不是把它打包:
index.html
<script
src="https://code.jquery.com/jquery-3.1.0.js"
integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk="
crossorigin="anonymous"
></script>
webpack.config.js
module.exports = {
//...
externals: {
jquery: 'jQuery',
},
};
這樣就剝離了那些不需要改動的依賴模塊,換句話,下面展示的代碼還可以正常運行:
import $ from 'jquery';
$('.my-element').animate(/* ... */);
具有外部依賴(external dependency)的 bundle 可以在各種模塊上下文(module context)中使用,例如 CommonJS, AMD, 全局變量和 ES2015 模塊。外部 library 可能是以下任何一種形式:
- root:可以通過一個全局變量訪問 library(例如,通過 script 標簽)。
- commonjs:可以將 library 作為一個 CommonJS 模塊訪問。
-
commonjs2:和上面的類似,但導出的是
module.exports.default. -
amd:類似于
commonjs,但使用 AMD 模塊系統(tǒng)
好了說了那么多,總結來說就是
將不怎么需要更新的第三方庫脫離webpack打包,不被打入bundle中,從而減少打包時間,但又不影響運用第三方庫的方式,例如import方式等
在vue項目里面 vue.config怎么去配置呢?
每次都手動去在index.html里面手動引入外部依賴的cdn路徑的。肯定不是我們需要的,這太笨了。
需要解決的問題:
a. 不打包指定的外部依賴
b. 在index.html自動引入外部依賴
怎么運用externals:
例如:
在index.html中引入CDN的資源react全家桶之類的資源
<script src="https://lib.baomitu.com/react/16.4.0-alpha.7926752/cjs/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.3.2/cjs/react-dom-server.browser.development.js"></script>
webpack.config.js配置如下:
module.exports = {
...
output: {
...
},
externals : {
xlsx: 'XLSX',
lodash: {
commonjs: 'lodash',
amd: 'lodash',
root: '_', // 指向全局變量
},
redux:'redux',
// 暫時注釋,此庫采用cdn引入,會導致報錯,cdn引入方式,是暴露了X6全局變量,Graph等屬性是掛載在X6全局變量里面,
// 但是里面掛載的對象屬性都不一樣。暫未找到解決方案
// '@antv/x6': 'X6',
'jquery':'jQuery' // 由于@antv/x6依賴了jQuery,這里配置忽略,采用cdn方式引入
}
}
這樣的話在應用程序中依舊可以以import的方式(還支持其他方式)引用:
import XLSX from 'xlsx'
import { createStore, combineReducers, applyMiddleware } from 'redux';
XLSX就是暴露的全局變量,xlsx庫的名稱,例如: import XLSX from 'xlsx'
這樣不僅之前對第三方庫的用法方式不變,還把第三方庫剝離出webpack的打包中,從而加速webpack的打包速度。
完整的externals配置如下,我已經(jīng)將externals對象單獨導出一個文件

可以看到上面還有個cdn對象,這個對象是干嘛用的,下面我們就來介紹一下。上面我們已經(jīng)介紹了配置externals 來忽略打包了。但是我們不可能真的就每次都去手動引入cdn鏈接,這樣就太蠢了。
此時我們肯定是希望運行打包命令的時候自動加載到模板里面。此時我們就需要借助一個webpack的插件 html-webpack-plugin
html-webpack-plugin的使用
html-webpack-plugin是webpack的一個插件,可以動態(tài)的創(chuàng)建和編輯html內(nèi)容,在html中使用esj語法可以讀取到配置中的參數(shù),簡化了html文件的構建。(
ejs知識點請自行百度,類似jsp跟asp的模板語法)
最基礎的使用方式
new HtmlWebpackPlugin({
// 其他默認配置
cdn: externalConfig// cdn配置
})
定義好了配置則可以再模板里面使用ejs模板語法來讀取這個變量了。模板語法可以if、for等函數(shù)
index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
<!--配置cdn 的css-->
<% if(htmlWebpackPlugin.options.cdn){ htmlWebpackPlugin.options.cdn.css.forEach(function(item){%>
<link href="<%=item%>" rel="prefetch" />
<% }) }%>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
<!--配置cdn 的js-->
<% if(htmlWebpackPlugin.options.cdn){ htmlWebpackPlugin.options.cdn.js.forEach(function(item){%>
<script src="<%=item%>"></script>
<% }) }%>
</body>
</html>
可以看到我先判斷有沒有cdn這個變量,然后再循環(huán)遍歷輸出。這樣就實現(xiàn)了編譯之后自動引入cdn外部依賴了。
在vue項目中。我們在vue.config中的 chainWebpack里面,其實我們不需要再去引入html-webpack-plugin這個庫了。因為已經(jīng)集成了的
chainWebpack: config => {
config.plugin('html').tap((args) => {
args[0].title = 'edge-compute-platform'
// 配置cdn
if (isProduction) {
args[0].cdn = externalsConfig.cdn
}
return args
})
}
看vue-cli源碼就知道config.plugin('html')就是html-webpack-plugin如果只是簡單定義一個變量而已就是上面這樣的用法。所以到這里引入cdn就完成了。