阅读目录
1.webpack 配置了解
webpack 的配置文件是一个 nodejs 的 module,使用 CommonJS 风格来编写的,比如如下:
- module.exports = {
- entry: './index',
- output: {
- path: __dirname + '/dist',
- filename: 'bundle.js'
- }
- }
webpack 的配置文件可以随便命名,默认为 webpack.config.js,因此在项目的根目录下,直接运行 webpack 就可以进行打包,但是也可以对 webpack 命名为其他的名字,比如把它放入 build/webpack.dev.js ,代码目录结构如下:
- ###目录结构如下:demo#工程名 | |---dist#打包后生成的目录文件 | |---node_modules#所有的依赖包 | |---src#项目的文件包 | ||---pages#存放所有页面的文件 | |||---page1 | ||||---index.html#第一个页面的html文件 | ||||---index.styl#第一个页面的css文件 | ||||---index.js#第一个页面的js文件 | |||---page2 | ||||---index.html#第二个页面的html文件 | ||||---index.styl#第二个页面的css文件 | ||||---index.js#第二个页面的js文件 | |---build | ||---webpack.base.js#webpack基本配置文件 | ||---webpack.dev.js#开发文件 | ||---webpack.build.js#打包线上文件 | |---.gitignore | |---README.md | |---package.json
因此我们在 package.json 配置文件如下:
- "scripts": {
- "dev": "node build/webpack.dev.js",
- "build": "node build/webpack.build.js"
- }
进入项目的根目录后,运行 npm run dev 即可进行打包。
1.1) 入口文件配置 entry 参数
entry 入口文件可以是字符串的单入口文件,也可以是数组的多入口文件,但是我们最常见的是一个对象的方式来组织入口文件。因此 object 中的 key 在 webpack 里相当于入口的 name,可以用来生成文件的路径,也可以使用来为此入口唯一的标识。
比如如下:
- entry: {
- 'page1': path.resolve(__dirname, '../src/pages/page1'),
- 'page2': path.resolve(__dirname, '../src/pages/page2')
- }
假如页面上有多个入口的话,这样一个个写比较麻烦,因此可以写一个函数如下:
- /*
- 获取项目中多个入口文件
- */
- function getEntries(paths) {
- // node 中同步获取文件列表
- var files = glob.sync(paths),
- entries = {};
- files.forEach(function(filepath) {
- var toArray = filepath.split('/');
- var filename = toArray[toArray.length - 2];
- entries[filename] = filepath;
- });
- return entries;
- }
- var entries = getEntries('./src/pages/*/index.js');
- Object.keys(entries).forEach(function(name) {
- entry[name] = entries[name]
- });
1.2) 输出文件:out 参数
output 参数是告诉 webpack 以什么方式来生成 / 输出文件,output 有几个常用的参数如:path, publicPath, filename, chunkFilename, 如下代码:
- output: {
- path: path.resolve(__dirname, '../dist'),
- publicPath: '/assets/',
- // 供插件在生产模式下更新内嵌到css、html文件里的相对路径url值
- filename: 'static/js/[name].js',
- chunkFilename: '[id].bundle.js',
- }
1.3) path 参数
path 参数表示生成文件的根目录,需要传入一个绝对路径,如:path.resolve(__dirname,'../dist'),会解析成 / 项目的根目录下 / dist 文件, path 参数和 filename 参数会共同组成入口文件的完整路径。
1.4) publicPath
该参数表示的是一个 URL 路径 (指向生成文件的根目录),可以用于 css/js/images/font 文件等资源的路径,可以确保网页正确的加载到这些资源文件。
1.5) publicPath 参数 和 path 参数的区别:
path 参数是针对本地文件系统的,但是 publicPath 则针对的是浏览器,它既可以是一个相对路径,比如 '../../dist', 也可以是一个绝对路径,比如:'http://www.xxx.com/', 那么什么时候使用相对路径呢?什么时候使用绝对路径呢?如果是引用本项目下的文件,最好使用相对路径,如果是引用跨项目的文件,需要使用绝对路径。
1.6) filename
filename 属性表示的是如何命名生成的入口文件,可以有如下规则:
1. [name], 指代入口文件的 name,也就是上面的 entry 中的 key。
2. [hash] 指代本次编译的一个 hash 版本,但是请注意,只要在同一次编译过程中生成的文件,这个 [hash] 值就是一样的,每一次编译,hash 值都是一样,也就是说不存在缓存文件,只要一编译所有的 hash
都会改变。
3. [chunkhash] 指代当前 chunk 的一个 hash 版本,也就是说,在每次编译过程中,每一个 chunk 的 hash 都是不一样的,如果某个 chunk 没有发生变化,那么该 chunk 的 hash 也不会发生变化,也就是可以理解如果页面的文件没有发生改变,那么 chunk 的 hash 也不会发生改变,因此未改变的文件会在缓存中读取。
1.7) chunkFilename
chunkFilename 参数 与 filename 参数类似,都是用来定义生成的命名方式的,只不过,chunkFilename 参数指定的是除了入口文件外的 chunk。
1.8) module 参数中的 rules 配置 (其实 rules 就相当于之前的 loaders):
- module: {
- rules: [{
- test: /\.js$/,
- include: [path.resolve(__dirname, 'src/pages/**/*.js')],
- exclude: /(node_modules)/,
- // 排除node_modules 文件
- use: {
- loader: 'babel-loader',
- options: {
- presets: ['es2015'],
- plugins: ['transform-runtime']
- }
- }
- }]
- }
下面对一些子参数进行说明:
test: test 其实是一个使用正则表达式匹配文件的一种方式,比如上面的是,匹配以 .js 结尾的文件。
include: 用来表示本 rules 配置是针对那些目录 / 文件,比如上面的代码配置是针对 src/pages/ 下的所有 js 文件的。
exclude: 是用来排除掉那些文件的,比如上面的是 /(node_modules)/ 的意思是 排除掉 node_modules 下的 js 文件的。
use: 使用到的 loader 的配置
use 下的 loader: 使用加载器名称。
options: 该参数是为当前 loader 设置的参数,对于 babel 也可以单独放在 .babelrc 文件中,也就是说该参数可以在项目的根目录不包含. babelrc 文件,把. babelrc 文件移到该配置项来即可。
2.webpack CommonsChunkPlugin 公共代码剥离
与单页应用相比,多页应用存在多个入口 (每个页面即一个入口),每个入口意味着一套完整的 js 代码 (包括业务逻辑和加载第三方库、框架)。然后在每个页面中分别加载该文件即可,
CommonsChunkPlugin: 该插件是一个可选用于建立一个独立文件 (chunk), 这个文件包括多个入口的 chunk 的公共模块,通过将公共模块拆出来,最终合成的文件能够在最开始的时候加载一次,便存到缓存中,供后续使用,优点是:会带来速度的提升,因为浏览器会迅速将公共的代码从缓存中提取出来
,而不是每次访问一个新页面时候,再去加载一个更大的文件。
CommonsChunkPlugin 初始化有哪些参数?
name: 给这个包含公共代码的 chunk 命名。
filename: 命名打包后生成的 js 文件。
minChunks 公共代码的判断标准:某个 js 模块被多少个 chunk(入口文件) 加载了才算是公共代码。
chunks,表示需要在哪些 chunk(配置中 entry 的每一项) 里寻找公共代码进行打包,默认不设置,那么它的提取范围为所有的 chunk。
下面是一个简单的 CommonsChunkPlugin 的实列含义:
- var commonsChunkPlugin = new webpack.optimize.CommonsChunkPlugin = ({
- name: 'vender',
- // 这公共代码的chunk命名为 'vender'
- filename: '[name].bundle.js',
- // 生成的文件名为 vender.bundle.js
- minChunks: 2,
- // 设定要有2个chunk(即2个页面)加载的js模块才会被纳入公共代码。
- chunks: ['pageA', 'pageB'],
- // 只使用这些入口的 chunk
- })
- var commonsChunkPlugin = new webpack.optimize.CommonsChunkPlugin = ({
- name: 'vender',
- // 这公共代码的chunk命名为 'vender'
- // filename: '[name].bundle.js', // 生成的文件名为 vender.bundle.js
- minChunks: Infinity,
- // 随着入口chunk越来越多,这个配置保证没其他的模块会打包进 公共的chunk
- })
下面是使用对 webpack CommonsChunkPlugin 详解的 demo:
- ###目录结构如下:demo#工程名 | |---dist#打包后生成的目录文件 | |---node_modules#所有的依赖包 | |---src#项目的文件包 | ||---common | |||---css#公用页面的css文件 | |||---js#公用页面的js文件 | ||---libs | |||---jquery.js#第三方库文件 | ||---main.js#入口文件 | |---.gitignore | |---README.md | |---index.html#首页文件 | |---package.json | |---webpack.config.js#配置文件 | |---webpack.production.config.js#上线打包配置文件
1.1) 未使用 CommonsChunkPlugin 打包情况下
webpack.config.js 代码如下:
- // 导入路径包
- const path = require('path');
- const webpack = require('webpack');
- const HtmlWebpackPlugin = require('html-webpack-plugin');
- module.exports = {
- //开启sourceMap便于调试
- devtool: 'eval-source-map',
- //入口文件,
- entry: {
- main: './src/main.js'
- },
- output: {
- // 输出文件到当前目录下的 build文件夹内
- path: path.resolve(__dirname, 'build'),
- publicPath: '/assets/',
- //指定资源文件引用的目录
- filename: 'bundle.js' // 文件名为 bundle.js
- //filename: '[name].js' // 可以打包为多个文件
- },
- resolve: {
- extensions: ['*', '.js', '.json'],
- },
- // 使用loader模块
- module: {
- /*
- * 在webpack2.0版本已经将 module.loaders 改为 module.rules, 当然module.loaders也是支持的。
- * 同时链式loader(用!连接)只适用于module.loader,同时-loader不可省略
- */
- rules: [{
- test: /\.css$/,
- use: ['style-loader', {
- loader: 'css-loader',
- options: {
- // modules: true // 设置css模块化,详情参考 https://github.com/css-modules/css-modules
- }
- },
- {
- loader: 'postcss-loader',
- // 参考 https://github.com/postcss/postcss-loader
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- }]
- },
- {
- test: /\.styl(us)?$/,
- use: ['style-loader', 'css-loader', {
- loader: "postcss-loader",
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- },
- 'stylus-loader']
- },
- {
- test: /\.js$/,
- loader: 'babel-loader',
- exclude: /node_modules/ //需要排除的目录
- }]
- },
- // 配置devServer各种参数
- devServer: {
- // contentBase: "./", // 本地服务器所加载的页面所在的目录
- hot: true,
- // 配置HMR之后可以选择开启
- historyApiFallback: true,
- // 不跳转
- inline: true // 实时刷新
- },
- plugins: [new HtmlWebpackPlugin({
- template: './index.html' // 模版文件
- }), new webpack.HotModuleReplacementPlugin(), // 热加载插件
- ]
- }
main.js 代码如下:
- require('./common/css/style.css');
- import './common/css/stylus.styl';
- require('./libs/jquery.js');
运行命令 npm run start 可以看到打包后的文件 bundle.js 代码内 包含第三方 jquery 框架的源码。
1.2)使用 CommonsChunkPlugin
单一入口文件,分文件输出
webpack.config.js 代码如下:
- // 导入路径包
- const path = require('path');
- const webpack = require('webpack');
- const HtmlWebpackPlugin = require('html-webpack-plugin');
- var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
- module.exports = {
- //开启sourceMap便于调试
- devtool: 'eval-source-map',
- //入口文件,
- entry: {
- main: './src/main.js'
- },
- output: {
- // 输出文件到当前目录下的 build文件夹内
- path: path.resolve(__dirname, 'build'),
- filename: '[name].js' // 可以打包为多个文件
- },
- resolve: {
- extensions: ['*', '.js', '.json'],
- },
- // 使用loader模块
- module: {
- /*
- * 在webpack2.0版本已经将 module.loaders 改为 module.rules, 当然module.loaders也是支持的。
- * 同时链式loader(用!连接)只适用于module.loader,同时-loader不可省略
- */
- rules: [{
- test: /\.css$/,
- use: ['style-loader', {
- loader: 'css-loader',
- options: {
- // modules: true // 设置css模块化,详情参考 https://github.com/css-modules/css-modules
- }
- },
- {
- loader: 'postcss-loader',
- // 参考 https://github.com/postcss/postcss-loader
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- }]
- },
- {
- test: /\.styl(us)?$/,
- use: ['style-loader', 'css-loader', {
- loader: "postcss-loader",
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- },
- 'stylus-loader']
- },
- {
- test: /\.js$/,
- loader: 'babel-loader',
- exclude: /node_modules/ //需要排除的目录
- }]
- },
- // 配置devServer各种参数
- devServer: {
- // contentBase: "./", // 本地服务器所加载的页面所在的目录
- hot: true,
- // 配置HMR之后可以选择开启
- historyApiFallback: true,
- // 不跳转
- inline: true // 实时刷新
- },
- plugins: [new HtmlWebpackPlugin({
- template: './index.html' // 模版文件
- }), new webpack.HotModuleReplacementPlugin(), // 热加载插件
- new CommonsChunkPlugin({
- name: 'chunk',
- filename: 'chunk.js' // 把公用的 webpackJsonp 打包到chunk.js 里面去
- })]
- }
main.js 代码如下:
- require('./common/css/style.css');
- import './common/css/stylus.styl';
- require('./common/js/test.js');
- require('./common/js/test2.js');
- require('./libs/jquery.js');
输出文件 chunk.js 和 main.js , chunk.js 是把公用的 webpackJsonp 打包到 chunk.js 代码里面去了。
但是 test.js 和 test2.js 及 jquery.js 被打包到 main.js 里面去了。
现在我们可以将 test.js 和 test2.js 打包到 chunk.js , 如下 webpack 配置代码如下:
- // 导入路径包
- const path = require('path');
- const webpack = require('webpack');
- const HtmlWebpackPlugin = require('html-webpack-plugin');
- var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
- module.exports = {
- //开启sourceMap便于调试
- devtool: 'eval-source-map',
- //入口文件,
- entry: {
- main: './src/main.js',
- chunk: ['./src/common/js/test.js', './src/common/js/test2.js']
- },
- output: {
- // 输出文件到当前目录下的 build文件夹内
- path: path.resolve(__dirname, 'build'),
- filename: '[name].js' // 可以打包为多个文件
- },
- resolve: {
- extensions: ['*', '.js', '.json'],
- },
- // 使用loader模块
- module: {
- /*
- * 在webpack2.0版本已经将 module.loaders 改为 module.rules, 当然module.loaders也是支持的。
- * 同时链式loader(用!连接)只适用于module.loader,同时-loader不可省略
- */
- rules: [{
- test: /\.css$/,
- use: ['style-loader', {
- loader: 'css-loader',
- options: {
- // modules: true // 设置css模块化,详情参考 https://github.com/css-modules/css-modules
- }
- },
- {
- loader: 'postcss-loader',
- // 参考 https://github.com/postcss/postcss-loader
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- }]
- },
- {
- test: /\.styl(us)?$/,
- use: ['style-loader', 'css-loader', {
- loader: "postcss-loader",
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- },
- 'stylus-loader']
- },
- {
- test: /\.js$/,
- loader: 'babel-loader',
- exclude: /node_modules/ //需要排除的目录
- }]
- },
- // 配置devServer各种参数
- devServer: {
- // contentBase: "./", // 本地服务器所加载的页面所在的目录
- hot: true,
- // 配置HMR之后可以选择开启
- historyApiFallback: true,
- // 不跳转
- inline: true // 实时刷新
- },
- plugins: [new HtmlWebpackPlugin({
- template: './index.html' // 模版文件
- }), new webpack.HotModuleReplacementPlugin(), // 热加载插件
- new CommonsChunkPlugin({
- name: 'chunk',
- filename: 'chunk.js' // 把公用的 webpackJsonp 打包到chunk.js 里面去
- })]
- }
1.3) 单一入口,模块重复引用,最终把相同的模块打包到 入口文件内。
webpack.config.js 配置如下:
- // 导入路径包
- const path = require('path');
- const webpack = require('webpack');
- const HtmlWebpackPlugin = require('html-webpack-plugin');
- var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
- module.exports = {
- //开启sourceMap便于调试
- devtool: 'eval-source-map',
- //入口文件,
- entry: {
- main: './src/main.js'
- },
- output: {
- // 输出文件到当前目录下的 build文件夹内
- path: path.resolve(__dirname, 'build'),
- filename: '[name].js' // 可以打包为多个文件
- },
- resolve: {
- extensions: ['*', '.js', '.json'],
- },
- // 使用loader模块
- module: {
- /*
- * 在webpack2.0版本已经将 module.loaders 改为 module.rules, 当然module.loaders也是支持的。
- * 同时链式loader(用!连接)只适用于module.loader,同时-loader不可省略
- */
- rules: [{
- test: /\.css$/,
- use: ['style-loader', {
- loader: 'css-loader',
- options: {
- // modules: true // 设置css模块化,详情参考 https://github.com/css-modules/css-modules
- }
- },
- {
- loader: 'postcss-loader',
- // 参考 https://github.com/postcss/postcss-loader
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- }]
- },
- {
- test: /\.styl(us)?$/,
- use: ['style-loader', 'css-loader', {
- loader: "postcss-loader",
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- },
- 'stylus-loader']
- },
- {
- test: /\.js$/,
- loader: 'babel-loader',
- exclude: /node_modules/ //需要排除的目录
- }]
- },
- // 配置devServer各种参数
- devServer: {
- // contentBase: "./", // 本地服务器所加载的页面所在的目录
- hot: true,
- // 配置HMR之后可以选择开启
- historyApiFallback: true,
- // 不跳转
- inline: true // 实时刷新
- },
- plugins: [new HtmlWebpackPlugin({
- template: './index.html' // 模版文件
- }), new webpack.HotModuleReplacementPlugin(), // 热加载插件
- new CommonsChunkPlugin({
- name: 'chunk',
- minChunks: 2
- })]
- }
main.js 代码如下:
- require('./common/css/style.css');
- import './common/css/stylus.styl';
- require('./common/js/test');
- require('./common/js/test2');
- test.js代码如下:
- require('./test2');
- var test1 = 11;
- exports.test1 = test1;
test2 模块被引用了两次打包,但是最终模块被打包到 main.js 里面去了,minChunks: 2 的含义是 至少入口文件引用 2 个相同的模块会被打包到 main.js 里面去。
1.4) 多入口,模块重复引用,将多个引用的模块被打包到公共模块。如下 webpack.config.js 代码:
- // 导入路径包
- const path = require('path');
- const webpack = require('webpack');
- const HtmlWebpackPlugin = require('html-webpack-plugin');
- var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
- module.exports = {
- //开启sourceMap便于调试
- devtool: 'eval-source-map',
- //入口文件,
- entry: {
- main: './src/main.js',
- main2: './src/main2.js',
- },
- output: {
- // 输出文件到当前目录下的 build文件夹内
- path: path.resolve(__dirname, 'build'),
- filename: '[name].js' // 可以打包为多个文件
- },
- resolve: {
- extensions: ['*', '.js', '.json'],
- },
- // 使用loader模块
- module: {
- /*
- * 在webpack2.0版本已经将 module.loaders 改为 module.rules, 当然module.loaders也是支持的。
- * 同时链式loader(用!连接)只适用于module.loader,同时-loader不可省略
- */
- rules: [{
- test: /\.css$/,
- use: ['style-loader', {
- loader: 'css-loader',
- options: {
- // modules: true // 设置css模块化,详情参考 https://github.com/css-modules/css-modules
- }
- },
- {
- loader: 'postcss-loader',
- // 参考 https://github.com/postcss/postcss-loader
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- }]
- },
- {
- test: /\.styl(us)?$/,
- use: ['style-loader', 'css-loader', {
- loader: "postcss-loader",
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- },
- 'stylus-loader']
- },
- {
- test: /\.js$/,
- loader: 'babel-loader',
- exclude: /node_modules/ //需要排除的目录
- }]
- },
- // 配置devServer各种参数
- devServer: {
- // contentBase: "./", // 本地服务器所加载的页面所在的目录
- hot: true,
- // 配置HMR之后可以选择开启
- historyApiFallback: true,
- // 不跳转
- inline: true // 实时刷新
- },
- plugins: [new HtmlWebpackPlugin({
- template: './index.html' // 模版文件
- }), new webpack.HotModuleReplacementPlugin(), // 热加载插件
- new CommonsChunkPlugin({
- name: 'chunk',
- minChunks: 2
- })]
- }
main.js 代码如下:
- require('./common/css/style.css');
- import './common/css/stylus.styl';
- require('./common/js/test');
- require('./common/js/test2');
- main2.js代码如下:
- var test1 = require('./common/js/test');
- var test2 = require('./common/js/test2');
- console.log(test1);
- console.log(test2);
如上代码: main.js 和 main2.js 都引用了 test.js 和 test2.js,打包后,test.js 和 test2.js 被打包到 chunk.js 内。 minChunks 的含义是:至少引用了
2 个相同的模块才会被打包到 chunk.js 里面去。默认为 2.
1.5)将第三方业务框架分开打包。
webpack.config.js 代码如下:
- // 导入路径包
- const path = require('path');
- const webpack = require('webpack');
- const HtmlWebpackPlugin = require('html-webpack-plugin');
- var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
- module.exports = {
- //开启sourceMap便于调试
- devtool: 'eval-source-map',
- //入口文件,
- entry: {
- main: './src/main.js',
- main2: './src/main2.js',
- jquery: ['./src/libs/jquery.js']
- },
- output: {
- // 输出文件到当前目录下的 build文件夹内
- path: path.resolve(__dirname, 'build'),
- filename: '[name].js' // 可以打包为多个文件
- },
- resolve: {
- extensions: ['*', '.js', '.json'],
- },
- // 使用loader模块
- module: {
- /*
- * 在webpack2.0版本已经将 module.loaders 改为 module.rules, 当然module.loaders也是支持的。
- * 同时链式loader(用!连接)只适用于module.loader,同时-loader不可省略
- */
- rules: [{
- test: /\.css$/,
- use: ['style-loader', {
- loader: 'css-loader',
- options: {
- // modules: true // 设置css模块化,详情参考 https://github.com/css-modules/css-modules
- }
- },
- {
- loader: 'postcss-loader',
- // 参考 https://github.com/postcss/postcss-loader
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- }]
- },
- {
- test: /\.styl(us)?$/,
- use: ['style-loader', 'css-loader', {
- loader: "postcss-loader",
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- },
- 'stylus-loader']
- },
- {
- test: /\.js$/,
- loader: 'babel-loader',
- exclude: /node_modules/ //需要排除的目录
- }]
- },
- // 配置devServer各种参数
- devServer: {
- // contentBase: "./", // 本地服务器所加载的页面所在的目录
- hot: true,
- // 配置HMR之后可以选择开启
- historyApiFallback: true,
- // 不跳转
- inline: true // 实时刷新
- },
- plugins: [new HtmlWebpackPlugin({
- template: './index.html' // 模版文件
- }), new webpack.HotModuleReplacementPlugin(), // 热加载插件
- new CommonsChunkPlugin({
- name: ['chunk', 'jquery'],
- minChunks: 2
- })]
- }
上面打包后 在页面上 会先加载 jquery.js,该模块包含了所有的模块文件,包括 webpackJSon 依赖代码,然后就是加载 chunk.js,最后就是 main.js 和 main2.js 了。
注意:webpack 使用插件 CommonsChunkPlugin 进行打包的时候,将符合引用次数的 (minChunks) 的模块打包到 name 参数的数组的第一个块内(chunk), 然后数组里面的依次打包,(查找 entry 里面的 key), CommonsChunkPlugin 中的最后一个块包含 webpack 生成的在浏览器上使用各个块的加载代码,
所以页面上使用的时候最后一个块必须先加载。
所以我们在页面上会先看到先 加载 jquery.js ,查看该代码就会看到包含所有的代码,然后加载 chunk.js 代码,最后就是 main.js 和 main2.js 代码了。
1.6)minChunks: infinity
webpack.config.js 代码如下:
- // 导入路径包
- const path = require('path');
- const webpack = require('webpack');
- const HtmlWebpackPlugin = require('html-webpack-plugin');
- var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
- module.exports = {
- //开启sourceMap便于调试
- devtool: 'eval-source-map',
- //入口文件,
- entry: {
- main: './src/main.js',
- main2: './src/main2.js',
- jquery: ['./src/libs/jquery.js'],
- },
- output: {
- // 输出文件到当前目录下的 build文件夹内
- path: path.resolve(__dirname, 'build'),
- filename: '[name].js' // 可以打包为多个文件
- },
- resolve: {
- extensions: ['*', '.js', '.json'],
- },
- // 使用loader模块
- module: {
- /*
- * 在webpack2.0版本已经将 module.loaders 改为 module.rules, 当然module.loaders也是支持的。
- * 同时链式loader(用!连接)只适用于module.loader,同时-loader不可省略
- */
- rules: [{
- test: /\.css$/,
- use: ['style-loader', {
- loader: 'css-loader',
- options: {
- // modules: true // 设置css模块化,详情参考 https://github.com/css-modules/css-modules
- }
- },
- {
- loader: 'postcss-loader',
- // 参考 https://github.com/postcss/postcss-loader
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- }]
- },
- {
- test: /\.styl(us)?$/,
- use: ['style-loader', 'css-loader', {
- loader: "postcss-loader",
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- },
- 'stylus-loader']
- },
- {
- test: /\.js$/,
- loader: 'babel-loader',
- exclude: /node_modules/ //需要排除的目录
- }]
- },
- // 配置devServer各种参数
- devServer: {
- // contentBase: "./", // 本地服务器所加载的页面所在的目录
- hot: true,
- // 配置HMR之后可以选择开启
- historyApiFallback: true,
- // 不跳转
- inline: true // 实时刷新
- },
- plugins: [new HtmlWebpackPlugin({
- template: './index.html' // 模版文件
- }), new webpack.HotModuleReplacementPlugin(), // 热加载插件
- new CommonsChunkPlugin({
- name: 'jquery',
- minChunks: 2
- })]
- }
main.js 代码如下:
- require('./common/css/style.css');
- import './common/css/stylus.styl';
- require('./common/js/test');
- require('./common/js/test2');
main2.js 代码如下:
- var test1 = require('./common/js/test');
- var test2 = require('./common/js/test2');
- console.log(test1);
- console.log(test2);
运行代码后 发现 main.js 和 main2.js 共同也能用的代码 test.js 和 test2.js 代码被打包到 jquery.js 里面去了。
当把 上面的 webpack.config.js 的代码 minChunks 修改为 minChunks: Infinity 后, test.js 和 test2.js 代码都被打包到 main.js 和 main2.js 代码内了。
1.7)参数 chunks
webpack.config.js 代码如下:
- // 导入路径包
- const path = require('path');
- const webpack = require('webpack');
- const HtmlWebpackPlugin = require('html-webpack-plugin');
- var CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");
- module.exports = {
- //开启sourceMap便于调试
- devtool: 'eval-source-map',
- //入口文件,
- entry: {
- main: './src/main.js',
- main2: './src/main2.js',
- jquery: ['./src/libs/jquery.js'],
- },
- output: {
- // 输出文件到当前目录下的 build文件夹内
- path: path.resolve(__dirname, 'build'),
- filename: '[name].js' // 可以打包为多个文件
- },
- resolve: {
- extensions: ['*', '.js', '.json'],
- },
- // 使用loader模块
- module: {
- /*
- * 在webpack2.0版本已经将 module.loaders 改为 module.rules, 当然module.loaders也是支持的。
- * 同时链式loader(用!连接)只适用于module.loader,同时-loader不可省略
- */
- rules: [{
- test: /\.css$/,
- use: ['style-loader', {
- loader: 'css-loader',
- options: {
- // modules: true // 设置css模块化,详情参考 https://github.com/css-modules/css-modules
- }
- },
- {
- loader: 'postcss-loader',
- // 参考 https://github.com/postcss/postcss-loader
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- }]
- },
- {
- test: /\.styl(us)?$/,
- use: ['style-loader', 'css-loader', {
- loader: "postcss-loader",
- options: {
- plugins: function() {
- return [require('autoprefixer')];
- }
- }
- },
- 'stylus-loader']
- },
- {
- test: /\.js$/,
- loader: 'babel-loader',
- exclude: /node_modules/ //需要排除的目录
- }]
- },
- // 配置devServer各种参数
- devServer: {
- // contentBase: "./", // 本地服务器所加载的页面所在的目录
- hot: true,
- // 配置HMR之后可以选择开启
- historyApiFallback: true,
- // 不跳转
- inline: true // 实时刷新
- },
- plugins: [new HtmlWebpackPlugin({
- template: './index.html' // 模版文件
- }), new webpack.HotModuleReplacementPlugin(), // 热加载插件
- new CommonsChunkPlugin({
- name: 'jquery',
- minChunks: 2,
- chunks: ['main', 'main2']
- })]
- }
chunks 代码 包含 ['main', 'main2'], 的含义是 都引用的模块才会打包到公用的模块 (jquery) 内。
查看 git 上的源码
3. 了解 ProvidePlugin 的用途
该插件的作用是 自动加载模块,典型的列子:比如自动加载 jquery,首先需要使用 npm install --save jquery 后,在 webpack.config.js 加如下配置:
- config.plugins.push(new Webpack.ProvidePlugin({
- $: 'jquery',
- jQuery: 'jquery'
- }));
这样配置完成后,我们在 index.js 可以直接使用 $ 和 jQuery 了,如:console.log(jQuery('body'));
3.2) 添加 hash
每次打完包后,我们看到 都会生成三个文件,分别是 manifest.js, vendor.js. 和 页面上的业务 js,manifest 是业务模块所有需要依赖的 js,比如:webpackJsonp,而 vendor.js 我们这边打包成第三方框架或库,我们这边是
jquery,每次打包后都会生成这三个文件,但是文件名都是一样的,浏览器可能缓存上一次的结果而无法加载最新的数据。因此我们需要添加 hash。
为了解决上述问题,我们需要为打包后的文件名添加 hash 值,这样每次修改后打包的 hash 文件值将会发生改变,浏览器会从服务器端下载最新的文件。
基本配置如下:
- module.exports = {
- output: {
- path: path.resolve(__dirname, '../dist'),
- publicPath: '',
- filename: isLine ? 'static/js/[name].[chunkhash:5].js': 'static/js/[name].js'
- }
- }
上面的代码 首先判断是否是在线上环境还是日常环境,如果是在线上打包的话,添加 [chunkHash:5] 变量,表示打包后的文件中加入 5 位的 hash 值。
3.3) 修改 vendor 配置
上面解决浏览器缓存问题后,每次打包生成一个新的 5 位的 hash 编码值,但是问题又来了,当我修改某一个 js 文件的时候,vendor.js 的 hash 值也跟着改变了,我们明白 vendor 是我们打包第三方库 jquery 的,jquery 我并没有改动,
为了解决上面的问题,我们需要使用 CommonsChunkPlugin 插件来配置;如下:
- module.exports = {
- new Webpack.optimize.CommonsChunkPlugin({
- name: ['vendor', 'manifest'],
- minChunks: 2
- })
- };
vendor.js 是打包库文件,而 manifest.js 是打包模块中依赖的文件,当某个 js 文件发生改变的话,manifest 是页面加载时启动文件,所以 hash 值会发生改变。而 vendor 代码被抽取出来后作为一个单独文件,源码没有改动的话,因此 hash 值就不会发生改变了。
webpack 多页应用架构系列实战 git 代码
来源: http://www.cnblogs.com/tugenhua0707/p/7191309.html