基于 Webpack 引入公共库的几种方式
以 jquery 和其插件 jquery-modal 为例,记录下引入公共库的几种方式。
为了方便,首先安装 jquery 和 jquery-modal:
cnpm i jquery jquery-modal --save
0. 直接引入
在具体的 js 文件中:
import $ from 'jquery'
import 'jquery-modal/jquery.modal.min.css'
import 'jquery-modal/jquery.modal.min.js'
$('body').append('<form id="myModal" class="modal"></from>')
$('#myModal').html('this is a modal')
$('#myModal').modal()
优点:方便。
缺点:
- 每个需要 jquery 的文件都要写单独引入的代码
- 打包的时候 jquery 会被打入每个写引入代码的文件中(代码重复处理)
打包结果:
Version: webpack 3.8.1
Time: 561ms
Asset Size Chunks Chunk Names
bundle.js 296 kB 0 [emitted] [big] bundle
[1] ./js/index.js 229 bytes {0} [built]
+ 7 hidden modules
1. ProvidePlugin
每个需要 jquery 的文件入口都需要写一句 import $ from 'jquery'
显然很蛋疼,能不能在需要的时候自动引入?ProvidePlugin 插件就为你做这件事的。
在 webpack.config.js 文件中 plugins 选项中新增配置:
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
'window.$': 'jquery'
})
]
ProvidePlugin 的机制是:当 webpack 加载到某个 js 模块里,出现了未定义且名称符合(字符串完全匹配)配置中 key 的变量时,会自动 require 配置中 value 所指定的 js 模块。
这个时候,如果文件中有用到 $
或者 jQuery
,window.jQuery
以及 window.$
的情况,就会自动引入 jquery。
具体的 js 文件可以省略包引入步骤了:
import 'jquery-modal/jquery.modal.min.css'
import 'jquery-modal/jquery.modal.min.js'
$('body').append('<form id="myModal" class="modal"></from>')
$('#myModal').html('this is a modal')
$('#myModal').modal()
优点:和直接引入相比,少写了一行代码。
缺点:直接引入中 2 的问题没有解决。
打包结果和 0.直接引入一样。
2. externals
将 jquery 这种库打入每个引入它的文件显然不好,webpack 有个 externals 的配置,可以让指定的包不打包,转而使用 cdn。
在 webpack.config.js 中新增:
externals: {
'jquery': '$'
}
它的意思就是,当你需要用到 jquery 包的时候,就去全局环境中找找有没有 $ 这玩意。所以我们同时需要引入 jquery 的 cdn。
html 文件可能是这样的:
<html>
<body>
<script src="//cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script src="bundle.js"></script>
</body>
</html>
优点:将库代码分离,需要用的时候通过 cdn 引入,解决了上面所说的第二个问题。
缺点:缺点也很明显,我觉得既然用了 webpack,就干脆不使用外联 script 脚本的方式,而且如果使用的库比较多,就需要引入多个 script 节点。而且,有的地方不能用 cdn,比如开发 chrome 插件,是不允许引入 cdn 的代码的,而且,很多文件并没有 cdn 文件。
打包结果:
Version: webpack 3.8.1
Time: 375ms
Asset Size Chunks Chunk Names
bundle.js 27.8 kB 0 [emitted] bundle
[0] ./js/index.js 232 bytes {0} [built]
+ 7 hidden modules
3. expose-loader
我们理想的结果是,可以把库代码(例如 jquery,react,lodash)打包进入一个文件。我们尝试对 Webpack 进行多入口配置。
将 webpack.config.js 文件修改:
entry: {
'bundle': './js/index.js',
'jquery': ['jquery'] // 将多个库文件打包成一个
},
output: {
filename: '[name].js'
}
理想的情况是用打包生成的 jquery.js 取代 cdn,但是现实很残酷,js 文件中报错了($ is not defined)。原因很简单,配置了 externals 的话,会去全局寻找 $
。如果也配上 externals,会发现 jquery.js 文件打包不上了。病急乱投医,配置 ProvidePlugin,但是依旧是之前的逻辑,新打出的 jquery.js 文件根本就没有用武之地了。
这个时候实际上需要的是 expose-loader 这个 loader(特别要注意的是,这个 loader 要尽量放到最前面!):
cnpm i expose-loader --save-dev
在 webpack 中添加如下:
module: {
rules: [
{
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: 'jQuery'
},{
loader: 'expose-loader',
options: '$'
}]
}
]
}
这个 loader 会将指定 js 模块 export 的变量声明为全局变量。
这表明 jquery 这个包会向全局暴露 jQuery
和 $
两个变量。
打个包:
Version: webpack 3.8.1
Time: 628ms
Asset Size Chunks Chunk Names
bundle.js 297 kB 0 [emitted] [big] bundle
jquery.js 272 kB 1 [emitted] [big] jquery
[0] (webpack)/buildin/global.js 488 bytes {0} {1} [built]
[4] ./js/index.js 302 bytes {0} [built]
[11] multi jquery 28 bytes {1} [built]
+ 9 hidden modules
jquery.js 被单独拎出来打包了,但是 bundle.js 这么大,似乎还把 jquery 打进入了。原因很简单,引入的 jquery-modal
文件依赖于 jquery。
可以做个测试,将 index.js 修改如下:
$.each([1, 2, 3], (index, item) => {
console.log(item)
})
打包:
Version: webpack 3.8.1
Time: 429ms
Asset Size Chunks Chunk Names
jquery.js 272 kB 0 [emitted] [big] jquery
bundle.js 2.79 kB 1 [emitted] bundle
[0] (webpack)/buildin/global.js 488 bytes {0} [built]
[1] ./js/index.js 308 bytes {1} [built]
[2] multi jquery 28 bytes {0} [built]
+ 3 hidden modules
缺点:无法解决 jquery 插件引入的 jquery 打包的问题(这个方案其实是要手动去掉类似 import $ from 'jquery'
的代码)。而且,jquery/react 这类的库,一般是不动的(所以 cdn 引入其实是一个好方案),不需要频繁打包。
另外,ProvidePlugin 和 expose-loader 做的事情看起来非常相似,如果你所有的 jQuery 插件都是用 webpack 来加载的话,的确用 ProvidePlugin 就足够了;但理想是丰满的,现实却是骨感的,总有那么些需求是只能用 <script> 来加载的。
4. DllPlugin
最后是终极操作。
新建 webpack.dll.config.js 文件:
const webpack = require('webpack')
module.exports = {
entry: {
"jquery": ['jquery'],
},
output: {
filename: '[name].js',
library: '[name]',
},
plugins: [
new webpack.DllPlugin({
path: 'manifest.json',
name: '[name]',
context: __dirname,
})
]
}
然后运行如下命令:
webpack --config webpack.dll.config.js
这个时候会生成 jquery.js 和 manifest.json 两个文件。
webpack.config.js 文件 plugins 选项下新增(需要保留 ProvidePlugin):
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
'window.$': 'jquery'
}),
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./manifest.json'),
}),
]
运行 webpack
进行打包:
Version: webpack 3.8.1
Time: 402ms
Asset Size Chunks Chunk Names
bundle.js 28.2 kB 0 [emitted] bundle
[0] delegated ./node_modules/._jquery@3.2.1@jquery/dist/jquery.js from dll-reference jquery 42 bytes {0} [built]
[1] ./js/index.js 302 bytes {0} [built]
+ 7 hidden modules
成功!不要忘了在 index.html 文件中引入第一步打包出来的 jquery.js 文件!
这个时候,无论代码中有没有类似 import $ from 'jquery'
,都不再会去打包 jquery。如果需要更新库文件(jquery 更新等),依赖(指 jquery 等)更新后,重新运行 webpack --config webpack.dll.config.js
即可
5. CommonsChunkPlugin
其实还可以用 CommonsChunkPlugin 这个插件,但是总觉得没有 DLL 优雅。
使用方式相当简单,入口配置新增一项:
entry: {
'bundle': './js/index.js',
vendor: ["jquery"],
}
然后 plugins 选项新增:
new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: 'vendor.bundle.js' })
运行 webpack
打包结果:
Version: webpack 3.8.1
Time: 957ms
Asset Size Chunks Chunk Names
bundle.js 25.7 kB 0 [emitted] bundle
vendor.bundle.js 274 kB 1 [emitted] [big] vendor
[1] ./js/index.js 299 bytes {0} [built]
[8] multi jquery 28 bytes {1} [built]
+ 7 hidden modules
注意要在 html 文件中优先引入打包结果 vendor.bundle.js !
基于 Webpack 引入公共库的几种方式的更多相关文章
- 不停止MySQL服务增加从库的两种方式
不停止MySQL服务增加从库的两种方式 转载自:http://lizhenliang.blog.51cto.com/7876557/1669829 现在生产环境MySQL数据库是一主一从,由于业务量访 ...
- 不停止MySQL服务增加从库的两种方式【转载】
现在生产环境MySQL数据库是一主一从,由于业务量访问不断增大,故再增加一台从库.前提是不能影响线上业务使用,也就是说不能重启MySQL服务,为了避免出现其他情况,选择在网站访问量低峰期时间段操作. ...
- 不停mysql服务添加从库的两种方式
现在生产环境MySQL数据库是一主一从,由于业务量访问不断增大,故再增加一台从库.前提是不能影响线上业务使用,也就是说不能重启MySQL服务,为了避免出现其他情况,选择在网站访问量低峰期时间段操作. ...
- 使用pip安装python库的几种方式
操作系统 : CentOS7.5.1804_x64 Python 版本 : 3.6.8 1.使用pip在线安装 1.1 安装单个package 格式如下: pip install SomePackag ...
- 基于 Webpack 引入 jquery 插件的笔记
如果都是基于 webpack(npm 上有包),那就非常顺利: import $ from 'jquery' import 'jquery-modal/jquery.modal.min.css' im ...
- 详解用webpack的CommonsChunkPlugin提取公共代码的3种方式(注意webpack4.0版本已不存在)
Webpack 的 CommonsChunkPlugin 插件,负责将多次被使用的 JS 模块打包在一起. CommonsChunkPlugin 能解决的问题 在使用插件前,考虑几个问题: 对哪些 c ...
- [转] 用webpack的CommonsChunkPlugin提取公共代码的3种方式
方式一,传入字符串参数 new webpack.optimize.CommonsChunkPlugin(‘common.js’), // 默认会把所有入口节点的公共代码提取出来,生成一个common. ...
- jQuery引入公共库问题
话说脚本最好放到底部,这样页面既可以逐步呈现,也可以提高下载,但是某些公共模块且有js效果,顺序优先公共库的话,效果是出不来的,所以以后就把公共库最好放在头部,(就是这个而已:http://apps. ...
- Android 接入 OpenCV库的三种方式
OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux.Windows.Android和Mac OS操作系统上.它轻量级而且高效——由一系列 C 函数和少 ...
随机推荐
- 【转载】Java系列笔记(1) - Java 类加载与初始化
Java系列笔记(1) - Java 类加载与初始化 原文地址:http://www.cnblogs.com/zhguang/p/3154584.html 目录 类加载器 动态加载 链接 初始化 示例 ...
- KendoUI 基础:Grid 绑定template展示
Grid 绑定template展示 <div id="TodayEditorGrid" style="margin:0 10px"></div ...
- 项目(1)----用户信息管理系统(5)---(剩余jsp界面)
完成剩余jsp界面 首页界面前面我写了,接下来还有就是一个显示所有用户界面 1:注册界面 2:显示所有用户信息界面 1:注册界面 <%@ page language="java&quo ...
- 栈stack(2):栈的链表实现
定义 从上一篇我们知道,栈(stack)是一个只允许一端进行删除插入操作的线性表.同时,我们联想到线性表的链式结构,其特点是用一组任意的存储单元存储线性表的数据元素,因此我们选择使用链表去实现栈,规定 ...
- iOS知识点集合--更改(2)
3.nsmutablearray *a 如果直接赋值 a = @[@"d",@""]; 这个时候a 是不可变的 字典也是如此 2.如果接口调用错误的话 打印re ...
- iOS APP内购
看到网上文章一大把,看了这个觉得挺不错的,谢谢 iOS大全 公众平台; 原文:http://mp.weixin.qq.com/s?__biz=MzAxMzE2Mjc2Ng==&mid=2652 ...
- C:宏定义的一些格式(怕忘记)
现在还没怎么用到宏定义,但以后肯定会经常用的,写下这盘,以后忘记了可以温故.首先宏定义必须写在函数之外,其作用域从宏定义命令起到源程序结束,也就是说一但定义系统就会分配内存,想让它结束用“#undef ...
- Sum of odd and even elements
Given an integer N, you have to print the sum of odd numbers and even numbers form 1 to N Input:Firs ...
- bzoj 1835: [ZJOI2010]base 基站选址
Description 有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di.需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci.如果在距离第i个村庄 ...
- MySQL 单实例编译安装 以及多实例安装简介
这是基本的安装教程,与牛逼的大神无关,或许是牛逼大神不用看就会安装吧. CentOS 6.5 Final x86_64 一.预安装软件包 1.开发包组合安装 yum groupinstall &qu ...