我的webpack,持续更新......
来源:互联网 发布:旺旺名是淘宝名吗 编辑:程序博客网 时间:2024/05/23 00:21
压缩js
使用自带的webpack.optimize.UglifyJsPlugin
const webpack = require('webpack');module.exports = function(env) { return { entry: { main: './index.js', }, output: { filename: '[chunkhash].[name].js', path: path.resolve(__dirname, 'dist') }, plugins: [ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false, drop_console: false, } }), ] }}
分离css
1、安装extract-text-webpack-plugin插件
npm i --save-dev extract-text-webpack-plugin@beta
2、在webpack.config.js中使用这个插件
var ExtractTextPlugin = require('extract-text-webpack-plugin');module.exports = function () { return { entry: './index.js', output: { path: './dist', filename: 'bundle.js' }, module: { rules: [{ test: /\.css$/, exclude: /node_modules/, use: ExtractTextPlugin.extract({ loader: 'css-loader' }) }] }, // devtool: 'source-map', plugins: [ new ExtractTextPlugin({ filename: 'bundle.css', disable: false, allChunks: true }) ] }}
提取公共文件
使用CommonsChunkPlugin的几种方式:
https://webpack.js.org/plugins/commons-chunk-plugin/#components/sidebar/sidebar.jsx
以下内容参考自:https://doc.webpack-china.org/guides/code-splitting-libraries/#-vendor-chunk
但是,如果我们改变应用的代码并且再次运行 webpack,可以看到 vendor 文件的 hash 改变了。即使我们把 vendor 和 main 的 bundle 分开了,也会发现 vendor bundle 会随着应用代码改变。
这意味着我们任然无法从浏览器缓存机制中受益,因为 vendor 的 hash 在每次构建中都会改变,浏览器也必须重新加载文件。这里的问题在于,每次构建时,webpack 生成了一些 webpack runtime 代码,用来帮助 webpack完成其工作。当只有一个 bundle 的时候,runtime 代码驻留在其中。但是当生成多个 bundle的时候,运行时代码被提取到了公共模块中,在这里就是 vendor 文件。
为了防止这种情况,我们需要将运行时代码提取到一个单独的 manifest 文件中。尽管我们又创建了另一个 bundle,其开销也被我们在 vendor 文件的长期缓存中获得的好处所抵消。
// index.jsvar moment = require('moment');var path = require('path');console.log(moment().format(), 11122334455);console.log(path.resolve(__dirname, '/dist'));console.log(path.join(__dirname, '/dist'));
// webpack.config.jsvar path = require('path');var webpack = require('webpack');var HtmlWebpackPlugin = require('html-webpack-plugin')module.exports = function(env) { return { entry: { main: './index.js', vendor: ['moment', 'path'] // 提取moment,path模块到wendor文件 }, output: { filename: '[name].js', // 原来是[chunkhash].[name].js path: path.resolve(__dirname, 'dist') }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ // name: 'vendor_modules', // minChunks: function (module) { // // 该配置假定你引入的 vendor 存在于 node_modules 目录中 // return module.context && module.context.indexOf('node_modules') !== -1; // } names: ['vendor', 'manifest'] }), new HtmlWebpackPlugin({ template: './index.html' //使用当前目录(根目录)下的index.html }) ] }}
使用webpack打包后,dist目录命令有(xxxxx表示hash值)
index.htmlxxxxx.main.jsxxxxx.manifest.js //webpack runtime 代码xxxxx.vendor.js
修改index.js代码,再次打包后,只会生更新manifest.js和main.js。而最大的共同包vendor.js是不会变得。通过hash值可以看到。这样vendor.js就可以缓存到浏览器了。
提取公共文件+
https://doc.webpack-china.org/guides/caching/
为了最小化生成的文件大小,webpack 使用标识符而不是模块名称。在编译期间,生成标识符并映射到块文件名,然后放入一个名为 chunk manifest 的 JavaScript 对象中。
为了生成保存在构建中的标识符,webpack 提供了 NamedModulesPlugin
(推荐用于开发模式)和HashedModuleIdsPlugin
(推荐用于生产模式)这两个插件。
然后将 chunk manifest(与引导/运行时代码一起)放入 entry chunk,这对 webpack 打包的代码工作是至关重要的。
改变其他文件时mainfest.js改变
这个问题和以前一样:每当我们改变代码的任何部分时,即使它的内容的其余部分没有改变,都会更新我们的入口块以便包含新的映射(manifest)。 这反过来,将产生一个新的哈希值并且使长效缓存失效。
使用ChunkManifestWebpackPlugin
要解决这个问题,我们应该使用 ChunkManifestWebpackPlugin,它会将 manifest 提取到一个单独的 JSON 文件中。 这将用一个 webpack runtime 的变量替换掉chunk manifest。 但我们可以做得更好;我们可以使用 CommonsChunkPlugin 将运行时提取到一个单独的入口起点(entry)中去。这里是一个更新后的 webpack.config.js,将生成我们的构建目录中的 manifest 和 runtime 文件:
// webpack.config.jsvar ChunkManifestPlugin = require("chunk-manifest-webpack-plugin"); module.exports = { /*...*/ plugins: [ /*...*/ new webpack.optimize.CommonsChunkPlugin({ name: ["vendor", "manifest"], // vendor libs + extracted manifest minChunks: Infinity, }), /*...*/ new ChunkManifestPlugin({ filename: "chunk-manifest.json", manifestVariable: "webpackManifest" }) ]};
因为我们从入口块(entry chunk)中移除了 manifest,所以我们现在有责任为 webpack 提供它。上面示例中的 manifestVariable 选项是全局变量的名称,webpack 将利用它查找 manifest JSON 对象。这个变量应该在我们引入 bundle 到 HTML 之前就定义好。这是通过在 HTML 中内联 JSON 的内容来实现的。我们的 HTML 头部应该像这样:
<!-- 这里我不明白webpackManifest的作用 --><html> <head> <script> //<![CDATA[ window.webpackManifest = {"0":"main.5f020f80c23aa50ebedf.js","1":"vendor.81adc64d405c8b218485.js"} //]]> </script> </head> <body> </body></html>
在结束时,文件的哈希值应该基于文件的内容。对此,我们可以使用 webpack-chunk-hash 或者 webpack-md5-hash。
所以最终的 webpack.config.js 看起来像这样:
var path = require("path");var webpack = require("webpack");var ChunkManifestPlugin = require("chunk-manifest-webpack-plugin");var WebpackChunkHash = require("webpack-chunk-hash");module.exports = { entry: { vendor: "./src/vendor.js", // vendor reference file(s) main: "./src/index.js" // application code }, output: { path: path.join(__dirname, "build"), filename: "[name].[chunkhash].js", chunkFilename: "[name].[chunkhash].js" }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ name: ["vendor", "manifest"], // vendor libs + extracted manifest minChunks: Infinity, }), new webpack.HashedModuleIdsPlugin(), new WebpackChunkHash(), new ChunkManifestPlugin({ filename: "chunk-manifest.json", manifestVariable: "webpackManifest" }) ]};
使用webpack-dev-server
关于API:https://doc.webpack-china.org/configuration/dev-server/
// package.json// 其中scripts这样设置"scripts": { "build": "webpack", "dev": "webpack-dev-server --devtool eval-source-map --progress --colors"},
- 关于devtool:https://doc.webpack-china.org/configuration/devtool/
- –progress 打印打包日志
- –colors带颜色的日志
// webpack.config.jsvar path = require('path');var webpack = require('webpack');var HtmlWebpackPlugin = require('html-webpack-plugin')module.exports = function(env) { return { entry: { main: './index.js', vendor: ['moment', 'path'] }, output: { // filename: '[chunkhash].[name].js', filename: '[name].js', publicPath: "/assets/", path: path.resolve(__dirname, 'build') }, devServer: { inline: true, port: 8099, contentBase: path.join(__dirname, 'build') }, plugins: [ new webpack.optimize.CommonsChunkPlugin({ names: ['vendor', 'manifest'] }), new HtmlWebpackPlugin({ template: './index.html' }), // etc. ] }}
使用npm run dev的时候,可以看到输出有以下:
不会实际生成文件夹,这一部分,推荐看这里:https://github.com/liangklfangl/webpack-dev-server/commit/9b9b86beffedee9c15c7ba3a807b30eb78d477e9
> webpack-dev-server --devtool eval-source-map --progress --colors 10% building modules 2/2 modules 0 activeProject is running at http://localhost:8099/webpack output is served from /assets/Content not from webpack is served from C:\Users\real\...\build 10%Hash: d968bc9b6ab05170f44fVersion: webpack 2.2.1
在 dev-server 的两种不同模式之间切换。默认情况下,应用程序启用内联模式(inline
mode)。这意味着一段处理实时重载的脚本被插入到你的包(bundle)中,并且构建消息将会出现在浏览器控制台。 也可以使用 iframe模式,它在通知栏下面使用<iframe>
标签,包含了关于构建的消息。
切换到 iframe 模式:inline:false
当使用模块热替换时,建议使用内联模式(inline mode)。output.path:指定编译目录而已(/build/),不能用于html中的js引用。
output.publicPath/devServer.publicPath:publicPath:虚拟目录,自动指向path编译目录(/assets/ => /build/)。html中引用js文件时,必须引用此虚拟路径(但实际上引用的是内存中的文件,既不是/build/也不是/assets/)。
devServer.contentBase:指明应用根目录,与上面两个配置项毫无关联。
所以在我打开localhost:8099的时候,如果设置了contentBase,那么就会跳到contentBase指明的目录,这里是:C:\Users\real\...\build
,这个目录是不会自动生成的,如果手动建立了这个目录,就会去找到这个目录下的index.html文件。否则,不能找到。
实际上可以访问的是:localhost:8099/assets/index.html,访问这个文件,会看到我们写的index.html,其中index.html自动引用了生成的main.js、vendor.js、manifest.js。并且当我们修改js文件的时候,页面会自动刷新。
热更新
webpack中文网的一个例子:实测可用。
https://doc.webpack-china.org/guides/hmr-react/
我的在这里:http://blog.csdn.net/real_bird/article/details/62927644
require.ensure
参考自:
http://blog.csdn.net/zhbhun/article/details/46826129
https://doc.webpack-china.org/guides/code-splitting-require/
说明: require.ensure在需要的时候才下载依赖的模块,当参数指定的模块都下载下来了(下载下来的模块还没执行),便执行参数指定的回调函数。require.ensure会创建一个chunk,且可以指定该chunk的名称,如果这个chunk名已经存在了,则将本次依赖的模块合并到已经存在的chunk中,最后这个chunk在webpack构建的时候会单独生成一个文件。
考虑下面的文件结构:
.├── dist├── js│ ├── a.js│ ├── b.js│ ├── c.js│ └── entry.js└── webpack.config.js
entry.js
require('./a');require.ensure(['./b'], function(require){ require('./c'); console.log('done!');});
a.js
console.log('***** I AM a *****');
b.js
console.log('***** I AM b *****');
c.js
console.log('***** I AM c *****');
webpack.config.js
var path = require('path');module.exports = function(env) { return { entry: './js/entry.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist'), // publicPath: 'https://cdn.example.com/assets/', // tell webpack where to load the on-demand bundles. publicPath: __dirname + '/dist/', pathinfo: true, // show comments in bundles, just to beautify the output of this example. // should not be used for production. } }}
通过执行这个项目的 webpack 构建,我们发现 webpack 创建了 2 个新的 bundle,bundle.js 和 0.bundle.js。
entry.js 和 a.js 被打包进 bundle.js。b.js和c.js被打包进0.bundle.js。0.bundle.js是按需加载的(通过output.publicPath,这里我修改了,以便能正确加载到)。
index.html
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Document</title> <script src="dist/bundle.js" charset="utf-8"></script></head><body></body></html>
打开这个文件后可以看到,它自动加载了0.bundle.js。
而在控制台输出的是:
***** I AM a ********** I AM c *****done!
这就说明了虽然require.ensure中虽然依赖了b.js,但是没有require('./b');
,所以就没有打印出来。模块虽然下载了,但必须手动require才会执行。就算没有使用require('./c');
,0.bundle.js还是会被加载的。注意到,这里是async
。
- 我的webpack,持续更新......
- 我的vim(持续更新)
- 我的blog索引[持续更新]
- 我的工具集(持续更新)
- 我的编程规范【持续更新中】
- 我的博客索引【持续更新】
- 我的工具集(持续更新)
- 我的命令技巧--持续更新
- 我的DOM库 (持续更新)
- 我的vim文件(持续更新)
- 我的代码库(持续更新...)
- 【持续更新】我遇到的问题
- MyEclispe我的常用操作---持续更新。
- 我知道的新技术(持续更新)
- 源码:我的关于NLP的博客(持续更新中...)
- 我的webpack配置文件
- 我的免费软件列表(持续更新中)
- 发生在我身上的囧事(持续更新)
- 前端开发大致总结
- 深度学习中的数据增强方法
- P3376 网络最大流
- 设计模式--工厂模式(C++实现)
- 洛谷 1462 通往奥格瑞玛的道路
- 我的webpack,持续更新......
- 数据结构学习之堆栈的链式存储C++实现
- 【天梯赛】L1--003 map典型的简单应用
- 虚析构函数
- 自动扫雷机
- PackageManager解析
- 在Ubuntu Server 14.04 LTS下安装VMware Tools(解决与主机共享问题---Mac虚拟机
- Android动画 帧动画、补间动画、属性动画 (二)
- 【线上第一解决方案】intellij如何把source文件和resource文件同时发布, java文件编译到输出folder, resource复制到output folder