基于 Webpack 引入公共库的几种方式
2017-11-05 16:06
369 查看
以 jquery 和其插件 jquery-modal 为例,记录下引入公共库的几种方式。
为了方便,首先安装 jquery 和 jquery-modal:
优点:方便。
缺点:
每个需要 jquery 的文件都要写单独引入的代码
打包的时候 jquery 会被打入每个写引入代码的文件中(代码重复处理)
打包结果:
在 webpack.config.js 文件中 plugins 选项中新增配置:
ProvidePlugin 的机制是:当 webpack 加载到某个 js 模块里,出现了未定义且名称符合(字符串完全匹配)配置中 key 的变量时,会自动 require 配置中 value 所指定的 js 模块。
这个时候,如果文件中有用到
具体的 js 文件可以省略包引入步骤了:
优点:和直接引入相比,少写了一行代码。
缺点:直接引入中 2 的问题没有解决。
打包结果和 0.直接引入一样。
在 webpack.config.js 中新增:
它的意思就是,当你需要用到 jquery 包的时候,就去全局环境中找找有没有 $ 这玩意。所以我们同时需要引入 jquery 的 cdn。
html 文件可能是这样的:
优点:将库代码分离,需要用的时候通过 cdn 引入,解决了上面所说的第二个问题。
缺点:缺点也很明显,我觉得既然用了 webpack,就干脆不使用外联 script 脚本的方式,而且如果使用的库比较多,就需要引入多个 script 节点。而且,有的地方不能用 cdn,比如开发 chrome 插件,是不允许引入 cdn 的代码的,而且,很多文件并没有 cdn 文件。
打包结果:
将 webpack.config.js 文件修改:
理想的情况是用打包生成的 jquery.js 取代 cdn,但是现实很残酷,js 文件中报错了($ is not defined)。原因很简单,配置了 externals 的话,会去全局寻找
这个时候实际上需要的是 expose-loader 这个 loader(特别要注意的是,这个 loader 要尽量放到最前面!):
在 webpack 中添加如下:
这个 loader 会将指定 js 模块 export 的变量声明为全局变量。
这表明 jquery 这个包会向全局暴露
打个包:
jquery.js 被单独拎出来打包了,但是 bundle.js 这么大,似乎还把 jquery 打进入了。原因很简单,引入的
可以做个测试,将 index.js 修改如下:
打包:
缺点:无法解决 jquery 插件引入的 jquery 打包的问题(这个方案其实是要手动去掉类似
另外,ProvidePlugin 和 expose-loader 做的事情看起来非常相似,如果你所有的 jQuery 插件都是用 webpack 来加载的话,的确用 ProvidePlugin 就足够了;但理想是丰满的,现实却是骨感的,总有那么些需求是只能用 <script> 来加载的。
新建 webpack.dll.config.js 文件:
然后运行如下命令:
这个时候会生成 jquery.js 和 manifest.json 两个文件。
webpack.config.js 文件 plugins 选项下新增(需要保留 ProvidePlugin):
运行
成功!不要忘了在 index.html 文件中引入第一步打包出来的 jquery.js 文件!
这个时候,无论代码中有没有类似
使用方式相当简单,入口配置新增一项:
然后 plugins 选项新增:
运行
注意要在 html 文件中优先引入打包结果 vendor.bundle.js !
为了方便,首先安装 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 !
相关文章推荐
- 基于react16 webpack3 搭建前端spa基础框架 react-router的4种异步加载方式
- 用webpack的CommonsChunkPlugin提取公共代码的3种方式
- 基于 Webpack 引入 jquery 插件的笔记
- 基于react16 webpack3 搭建前端spa基础框架 react-router的4种异步加载方式
- 基于MVC4+EasyUI的Web开发框架经验总结(12)--利用Jquery处理数据交互的几种方式
- 二、spring Boot构建的Web应用中,基于MySQL数据库的几种数据库连接方式进行介绍
- (转)基于MVC4+EasyUI的Web开发框架经验总结(12)--利用Jquery处理数据交互的几种方式
- NetBeans Visual Web Pack 5.5以可视方式快速构建基于标准的 Web 应用程序。
- HtmlWebpackPlugin以inine方式引入JS/CSS文件
- 基于MVC+EasyUI的Web开发框架经验总结(12)--利用Jquery处理数据交互的几种方式
- 详解用webpack的CommonsChunkPlugin提取公共代码的3种方式
- web.xml中配置url-pattern的几种方式
- 基于react+redux+webpack的前端框架
- 关于将ECharts引入至项目中的几种方式
- 基于hadoop2.5提交mapreduce任务的几种方式
- web中缓存的几种方式
- 如何在 webpack 中引入未模块化的库,如 Zepto
- 在c#中使用HttpWebRequest时的几种提交数据方式学习和分析
- Web负载均衡的几种实现方式
- 整理asp.net开发中几种常见公共捕获异常方式