文章目录
作为一名踏足前端时间不长的小开发必须得聊一聊
webpack
,刚开始接触webpack时第一反应这是啥(⊙_⊙)? 怎么这么复杂,感觉好难呀,算了先不管这些!时间是个好东西呀,随着对
前端工程化
的实践和理解慢慢加深,跟webpack接触越来越多,最终还是被ta折服,不禁高呼一声“
webpack yyds(永远滴神)!
”
去年年中就想写一些关于webpack的文章,由于各种原因耽搁了(主要是觉得对webpack理解还不够,不敢妄自下笔);临近年节,时间也有些了,与其 "摸鱼"不如摸摸webpack,整理一些"年货"分享给需要的xdm!后续会继续写一些【 Webpack】系列文章,xdm监督···
导读
本文主要通过实现一个cdn优化
的插件CdnPluginInject
介绍下webpack
的插件plugin
开发的具体流程,中间会涉及到html-webpack-plugin
插件的使用、vue/cli3+
项目中webpack插件的配置以及webpack相关知识点的说明。全文大概2800+字,预计耗时5~10分钟,希望xdm看完有所学、有所思、有所输出!
**注意:**文章中实例基于vue/cli3+
工程展开!
一、cdn常规使用
index.html:
<head>
···
</head>
<body>
<div id="app"></div>
<script src="https://cdn.bootcss.com/vuex/3.1.0/vuex.min.js"></script>
<script src="https://cdn.bootcss.com/vue-router/3.0.2/vue-router.min.js"></script>
···
</body>
vue.config.js:
module.exports = {
···
configureWebpack: {
···
externals: {
'vuex': 'Vuex',
'vue-router': 'VueRouter',
···
}
},
二、开发一个webpack plugin
webpack官网如此介绍到:插件向第三方开发者提供了 webpack 引擎中完整的能力。使用阶段式的构建回调,开发者可以引入它们自己的行为到 webpack 构建流程中。创建插件比创建 loader 更加高级,因为你将需要理解一些 webpack 底层的内部特性来实现相应的钩子!
一个插件由以下构成:
- 一个具名 JavaScript 函数。
- 在它的原型上定义 apply 方法。
- 指定一个触及到 webpack 本身的 事件钩子。
- 操作 webpack 内部的实例特定数据。
- 在实现功能后调用 webpack 提供的 callback。
// 一个 JavaScript class class MyExampleWebpackPlugin { // 将 `apply` 定义为其原型方法,此方法以 compiler 作为参数 apply(compiler) { // 指定要附加到的事件钩子函数 compiler.hooks.emit.tapAsync( 'MyExampleWebpackPlugin', (compilation, callback) => { console.log('This is an example plugin!'); console.log('Here’s the `compilation` object which represents a single build of assets:', compilation); // 使用 webpack 提供的 plugin API 操作构建结果 compilation.addModule(/* ... */); callback(); } ); } }
三、cdn优化插件实现
思路:
- 1、创建一个具名
JavaScript
函数(使用ES6
的class
实现); - 2、在它的原型上定义
apply
方法; - 3、指定一个触及到 webpack 本身的事件钩子(此处触及
compilation
钩子:编译(compilation)创建之后,执行插件); - 4、在钩子事件中操作
index.html
(将cdn
的script标签
插入到index.html
中); - 5、在
apply
方法执行完之前将cdn的参数
放入webpack
的外部扩展externals
中; - 6、在实现功能后调用
webpack
提供的callback
;
实现步骤:
1、创建一个具名JavaScript
函数(使用ES6
的class
实现)
创建类cdnPluginInject
,添加类的构造函数接收传递过来的参数;此处我们定义接收参数的格式如下:
modules:[
{
name: "xxx", //cdn包的名字
var: "xxx", //cdn引入库在项目中使用时的变量名
path: "http://cdn.url/xxx.js" //cdn的url链接地址
},
···
]
定义类的变量modules
接收传递的cdn参数
的处理结果:
class CdnPluginInject {
constructor({
modules,
}) {
// 如果是数组,将this.modules变换成对象形式
this.modules = Array.isArray(modules) ? {
["defaultCdnModuleKey"]: modules } : modules;
}
···
}
module.exports