webpack使用HtmlWebpackPlugin進(jìn)行cdn配置

其中build文件夾中的webpack.prod.conf.js是我們主要注意的文件,我們在該文件中動(dòng)態(tài)設(shè)置不需要被打包的模塊并構(gòu)建出合適的鏈接。

確定需要使用CDN的模塊

在webpack項(xiàng)目中,所引入的第三方資源會(huì)被統(tǒng)一打包進(jìn)vender文件中,我們通過webpack的externals屬性可以設(shè)置打包時(shí)排除該模塊,詳情說明見外部擴(kuò)展(externals)。

在前面的步驟中,我們創(chuàng)建的項(xiàng)目包括vue、vue-router,在正式開發(fā)在還會(huì)有ui庫,如element-ui,為了方便演示,我們再安裝element-ui和axios兩個(gè)模塊,并實(shí)現(xiàn)在構(gòu)建是把這是個(gè)模塊以cdn的形式引入。

所需模塊
vue
vue-router
element-ui
axios
$ npm install element-ui axios  -S

注意安裝時(shí)記得-S,它的作用是安裝完后在package.json項(xiàng)目文件中插入記錄,后續(xù)操作需要讀取已安裝模塊

確定CDN資源URI

對于cdn,我們可以自己搭建,也可以使用專業(yè)的cdn服務(wù)商,這里使用免費(fèi)的cdn bootcdn。選用免費(fèi)cdn有很多好處,但畢竟有隱患,那就是服務(wù)有可能會(huì)奔潰。

bootcdn https://www.bootcdn.cn

依次搜索出前面模塊,結(jié)果如下

模塊 版本 js css
vue 2.5.2 https://cdn.bootcss.com/vue/2.5.2/vue.min.js -
vue-router 3.0.1 https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js -
element-ui 2.6.3 https://cdn.bootcss.com/element-ui/2.6.1/index.js https://cdn.bootcss.com/element-ui/2.6.1/theme-chalk/index.css
axios 0.18.0 https://cdn.bootcss.com/axios/0.18.0/axios.min.js -

按照規(guī)律,得出cdn資源路徑規(guī)則為

https://cdn.bootcss.com + 模塊名 + 版本號(hào) + 具體路徑
其他cdn服務(wù)商同理

打包前的處理

build/utils.js添加讀取事件

使用cdn其實(shí)也就是在webpack熱啟動(dòng)和打包項(xiàng)目的時(shí)候動(dòng)態(tài)插入script和style鏈接,為了方便維護(hù),我們通過在build/utils.js文件上添加幾個(gè)方法,將來在webpack.dev.conf.js和webpack.prod.conf.js上可以使用。

如果沒有build/utils.js,可以在其他文件上添加,只要在后續(xù)步驟中能操作到就行

1.添加cdn根地址

// build/utils.js 國內(nèi)免費(fèi)cdn鏡像源
exports.cdnBaseHttp = 'https://cdn.bootcss.com';

2.添加cdn模塊 按照需要?jiǎng)h改

//  build/utils.js external配置
exports.externalConfig = [
  { name: 'vue', scope: 'Vue', js: 'vue.min.js' },
  { name: 'vue-router', scope: 'VueRouter', js: 'vue-router.min.js' },
  { name: 'axios', scope: 'axios', js: 'axios.min.js' },
  { name: 'element-ui', scope: 'ELEMENT', js: 'index.js', css: 'theme-chalk/index.css' },
];

name: 模塊名稱,與package.json同名
scope: 模塊作用域命名
js:js地址
css: css地址

這里特別注意scope,它是webpack配置的external參數(shù)下的信息,比如vue的作用域命名是Vue,vue-router的作用域命名是VueRouter,element-ui的作用域命名是ELEMENT,同理,jq的作用域命名是JQuery,具體做法是先引入該資源,然后在控制臺(tái)依次輸入近似的值,一個(gè)個(gè)匹配(目前沒找到更好的做法)。

3.添加獲取版本號(hào)方法

// build/utils.js 獲取模塊版本號(hào)
exports.getModulesVersion = () => {
  let mvs = {};
  let regexp = /^npm_package_.{0,3}dependencies_/gi;
  for (let m in process.env) { // 從node內(nèi)置參數(shù)中讀取,也可直接import 項(xiàng)目文件進(jìn)來
    if (regexp.test(m)) { // 匹配模塊
       // 獲取到模塊版本號(hào)
      mvs[m.replace(regexp, '').replace(/_/g, '-')] = process.env[m].replace(/(~|\^)/g, '');
    }
  }
  return mvs;
};

4.導(dǎo)出不需要被打包的cdn模塊配置重點(diǎn)

// build/utils.js
exports.getExternalModules = config => {
  let externals = {}; // 結(jié)果
  let dependencieModules = this.getModulesVersion(); // 獲取全部的模塊和版本號(hào)
  config = config || this.externalConfig; // 默認(rèn)使用utils下的配置
  config.forEach(item => { // 遍歷配置
    if (item.name in dependencieModules) {
      let version = dependencieModules[item.name];
      // 拼接css 和 js 完整鏈接
      item.css = item.css && [this.cdnBaseHttp, item.name, version, item.css].join('/');
      item.js = item.js && [this.cdnBaseHttp, item.name, version, item.js].join('/');
      externals[item.name] = item.scope; // 為打包時(shí)準(zhǔn)備
    } else {
      throw new Error('相關(guān)依賴未安裝,請先執(zhí)行npm install ' + item.name);
    }
  });
  return externals;
};

webpack.dev.conf.js添加cdn配置

在webpack熱啟動(dòng)本地調(diào)試的時(shí)候,我們可以使用cdn。

1.獲取cdn配置
// build/webpack.dev.conf.js 大概在15行
const externalConfig = JSON.parse(JSON.stringify(utils.externalConfig));  // 讀取配置
utils.getExternalModules(externalConfig); // 獲取到合適的路徑(引用類型,自動(dòng)改變)
 
// const devWebpackConfig = merge ....... 

在build/webpack.dev.conf.js中,默認(rèn)已經(jīng)引入了utils.js,所以可以直接調(diào)用相關(guān)方法,如果是自定義的文件,記得引入。

2.HtmlWebpackPlugin插件中導(dǎo)出cdn

緊接著我們在該文件下找到devWebpackConfig下的plugins下的HtmlWebpackPlugin插件,它的作用是動(dòng)態(tài)構(gòu)建html頁面,原始配置如下:

new HtmlWebpackPlugin({
  filename: 'index.html',
  template: 'index.html',
  inject: true
}),
// 代表處理根目錄下的index.html文件

我們可以往里面添加點(diǎn)自定義屬性,方便在index.html中調(diào)用。,修改如下:

new HtmlWebpackPlugin({
 filename: 'index.html',
 template: 'index.html',
 inject: true,
 cdnConfig: externalConfig, // cdn配置
 onlyCss: true, //dev下只加載css
}),

其中cdnConfig和onlyCss自定義屬性,在html上通過htmlWebpackPlugin.options可以讀取到。
更多html-webpack-plugin配置情況官網(wǎng),這里暫時(shí)不需要更多。

webpack.prod.conf.js添加cdn配置和忽略模塊
在打包的時(shí)候,我們使用cdn,配置和前面dev的差不多,只不過需要做多一步。

1.獲取cdn配置
// build/webpack.prod.conf.js 大概在15行
const externalConfig = JSON.parse(JSON.stringify(utils.externalConfig)); // 讀取配置
const externalModules = utils.getExternalModules(externalConfig); // 獲取到合適路徑和忽略模塊
 
// const webpackConfig = merge(baseWebpackConfig.... 

注意此處的externalModules,后面用到,也就是比dev多的步驟。

2.webpck配置加多個(gè)屬性externals

externals代表構(gòu)建時(shí)不需要被處理的模塊,也就是前面說的scope需要注意的地方。

// build/webpack.prod.conf.js
const webpackConfig = merge(baseWebpackConfig, {
  externals: externalModules, // 構(gòu)建時(shí)忽略的資源
 
  // 其他屬性
}
3.HtmlWebpackPlugin插件中導(dǎo)出cdn

和dev一樣,我們修改webpackConfig下的plugins下的HtmlWebpackPlugin插件配置 (這里的默認(rèn)配置比dev的多,主要是css壓縮和js壓縮相關(guān))

new HtmlWebpackPlugin({
   // 其他默認(rèn)配置
  cdnConfig: externalConfig, // cdn配置
  onlyCss: false, //加載css
}),

加入和dev一樣的兩個(gè)配置,不過需要把onlyCss改為true,因?yàn)槲覀兿M虬鼤r(shí)不單單使用css。

index.html插入相關(guān)鏈接

webpack配置已經(jīng)完成,在html-webpack-plugin中已經(jīng)添加了相關(guān)參數(shù),我們再在頁面上可以直接使用,使用語法是ejs,和asp.net,jsp,php類似。

<!DOCTYPE html>
<html>
  <head>
   <!-- 其他標(biāo)簽 -->
    <% htmlWebpackPlugin.options.cdnConfig.forEach(function(item){ if(item.css){ %>
    <link href="<%= item.css %>" rel="stylesheet" />
    <% }}) %>
  </head>
  <body>
   <!-- 其他標(biāo)簽 -->
    <% htmlWebpackPlugin.options.cdnConfig.forEach(function(item){ if(item.js && !htmlWebpackPlugin.options.onlyCss){ %>
    <script type="text/javascript" src="<%= item.js %>"></script>
    <% }}) %>
    <!-- built files will be auto injected -->
  </body>
</html>
```
通過<% %> 和 htmlWebpackPlugin.options 用js遍歷插入link標(biāo)簽和script標(biāo)簽。

ps: 修改了webpack配置,需要重啟項(xiàng)目才會(huì)生效




 
        
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容