webpack使用HtmlWebpackPlugin进行cdn配置

其中build文件夹中的webpack.prod.conf.js是我们主要注意的文件,我们在该文件中动态设置不需要被打包的模块并构建出合适的链接。

确定需要使用CDN的模块

在webpack项目中,所引入的第三方资源会被统一打包进vender文件中,我们通过webpack的externals属性可以设置打包时排除该模块,详情说明见外部扩展(externals)

在前面的步骤中,我们创建的项目包括vue、vue-router,在正式开发在还会有ui库,如element-ui,为了方便演示,我们再安装element-ui和axios两个模块,并实现在构建是把这是个模块以cdn的形式引入。

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

注意安装时记得-S,它的作用是安装完后在package.json项目文件中插入记录,后续操作需要读取已安装模块

确定CDN资源URI

对于cdn,我们可以自己搭建,也可以使用专业的cdn服务商,这里使用免费的cdn bootcdn。选用免费cdn有很多好处,但毕竟有隐患,那就是服务有可能会奔溃。

bootcdn https://www.bootcdn.cn

依次搜索出前面模块,结果如下

模块 版本 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 -

按照规律,得出cdn资源路径规则为

https://cdn.bootcss.com + 模块名 + 版本号 + 具体路径
其他cdn服务商同理

打包前的处理

build/utils.js添加读取事件

使用cdn其实也就是在webpack热启动和打包项目的时候动态插入script和style链接,为了方便维护,我们通过在build/utils.js文件上添加几个方法,将来在webpack.dev.conf.js和webpack.prod.conf.js上可以使用。

如果没有build/utils.js,可以在其他文件上添加,只要在后续步骤中能操作到就行

1.添加cdn根地址

// build/utils.js 国内免费cdn镜像源
exports.cdnBaseHttp = 'https://cdn.bootcss.com';

2.添加cdn模块 按照需要删改

//  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参数下的信息,比如vue的作用域命名是Vue,vue-router的作用域命名是VueRouter,element-ui的作用域命名是ELEMENT,同理,jq的作用域命名是JQuery,具体做法是先引入该资源,然后在控制台依次输入近似的值,一个个匹配(目前没找到更好的做法)。

3.添加获取版本号方法

// build/utils.js 获取模块版本号
exports.getModulesVersion = () => {
  let mvs = {};
  let regexp = /^npm_package_.{0,3}dependencies_/gi;
  for (let m in process.env) { // 从node内置参数中读取,也可直接import 项目文件进来
    if (regexp.test(m)) { // 匹配模块
       // 获取到模块版本号
      mvs[m.replace(regexp, '').replace(/_/g, '-')] = process.env[m].replace(/(~|\^)/g, '');
    }
  }
  return mvs;
};

4.导出不需要被打包的cdn模块配置重点

// build/utils.js
exports.getExternalModules = config => {
  let externals = {}; // 结果
  let dependencieModules = this.getModulesVersion(); // 获取全部的模块和版本号
  config = config || this.externalConfig; // 默认使用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; // 为打包时准备
    } else {
      throw new Error('相关依赖未安装,请先执行npm install ' + item.name);
    }
  });
  return externals;
};

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

在webpack热启动本地调试的时候,我们可以使用cdn。

1.获取cdn配置
// build/webpack.dev.conf.js 大概在15行
const externalConfig = JSON.parse(JSON.stringify(utils.externalConfig));  // 读取配置
utils.getExternalModules(externalConfig); // 获取到合适的路径(引用类型,自动改变)
 
// const devWebpackConfig = merge ....... 

在build/webpack.dev.conf.js中,默认已经引入了utils.js,所以可以直接调用相关方法,如果是自定义的文件,记得引入。

2.HtmlWebpackPlugin插件中导出cdn

紧接着我们在该文件下找到devWebpackConfig下的plugins下的HtmlWebpackPlugin插件,它的作用是动态构建html页面,原始配置如下:

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

我们可以往里面添加点自定义属性,方便在index.html中调用。,修改如下:

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配置情况官网,这里暂时不需要更多。

webpack.prod.conf.js添加cdn配置和忽略模块
在打包的时候,我们使用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配置加多个属性externals

externals代表构建时不需要被处理的模块,也就是前面说的scope需要注意的地方。

// build/webpack.prod.conf.js
const webpackConfig = merge(baseWebpackConfig, {
  externals: externalModules, // 构建时忽略的资源
 
  // 其他属性
}
3.HtmlWebpackPlugin插件中导出cdn

和dev一样,我们修改webpackConfig下的plugins下的HtmlWebpackPlugin插件配置 (这里的默认配置比dev的多,主要是css压缩和js压缩相关)

new HtmlWebpackPlugin({
   // 其他默认配置
  cdnConfig: externalConfig, // cdn配置
  onlyCss: false, //加载css
}),

加入和dev一样的两个配置,不过需要把onlyCss改为true,因为我们希望打包时不单单使用css。

index.html插入相关链接

webpack配置已经完成,在html-webpack-plugin中已经添加了相关参数,我们再在页面上可以直接使用,使用语法是ejs,和asp.net,jsp,php类似。

<!DOCTYPE html>
<html>
  <head>
   <!-- 其他标签 -->
    <% htmlWebpackPlugin.options.cdnConfig.forEach(function(item){ if(item.css){ %>
    <link href="<%= item.css %>" rel="stylesheet" />
    <% }}) %>
  </head>
  <body>
   <!-- 其他标签 -->
    <% 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标签和script标签。

ps: 修改了webpack配置,需要重启项目才会生效




 
        
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容