阅读目录

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代码

webpack 多页应用架构系列实战的更多相关文章

  1. webpack多页应用架构系列(一):一步一步解决架构痛点

    这系列文章讲什么? 前些时间,写过一个项目,前后端分离,没有借助任何框架,项目页面特别的多,页面都是html直接写的,许多公共html,写了好多处,有一个地方需要改就得改好多地方,js也是随意写,每个 ...

  2. Aibabelx-shop 大型微服务架构系列实战之技术选型

    一.本项目涉及编程语言java,scala,python,涉及的技术如下: 1.微服务架构: springboot springcloud mybatisplus shiro 2.全文检索技术 sol ...

  3. Linux运维企业架构项目实战系列

    Linux运维企业架构项目实战系列 项目实战1—LNMP的搭建.nginx的ssl加密.权限控制的实现 项目实战2—LVS.nginx实现负载均衡系列2.1 项目实战2.1—实现基于LVS负载均衡集群 ...

  4. [原创].NET 分布式架构开发实战五 Framework改进篇

    原文:[原创].NET 分布式架构开发实战五 Framework改进篇 .NET 分布式架构开发实战五 Framework改进篇 前言:本来打算这篇文章来写DAL的重构的,现在计划有点改变.之前的文章 ...

  5. [原创].NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇)

    原文:[原创].NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇) .NET 分布式架构开发实战之四 构建从理想和实现之间的桥梁(前篇) 前言:上一篇文章讲述了一些实现DAL的理论,本 ...

  6. [原创].NET 分布式架构开发实战之三 数据访问深入一点的思考

    原文:[原创].NET 分布式架构开发实战之三 数据访问深入一点的思考 .NET 分布式架构开发实战之三 数据访问深入一点的思考 前言:首先,感谢园子里的朋友对文章的支持,感谢大家,希望本系列的文章能 ...

  7. [原创].NET 分布式架构开发实战之二 草稿设计

    原文:[原创].NET 分布式架构开发实战之二 草稿设计 .NET 分布式架构开发实战之二 草稿设计 前言:本篇之所以称为草稿设计,是因为设计的都是在纸上完成的.反映了一个思考的过程. 本篇的议题如下 ...

  8. [原创].NET 分布式架构开发实战之一 故事起源

    原文:[原创].NET 分布式架构开发实战之一 故事起源 .NET 分布式架构开发实战之一 故事起源 前言:本系列文章主要讲述一个实实在在的项目开发的过程,主要包含:提出问题,解决问题,架构设计和各个 ...

  9. .NET-记一次架构优化实战与方案-目录

    前言 本系列是根据我公司的某块业务优化进行改写的,为了避免触发法律的红线,我对部分代码做了截取并打码. 因为优化方案是针对现有业务的问题情况进行的,不做任何太过过分吹牛逼.一切以基于现有的业务,优化处 ...

随机推荐

  1. Ajax请求汇总(一)

    刚开始结束Ajax请求的时候,那真的是迷迷糊糊,昏天暗地,通过学习的深入和翻阅各种资料.求助度娘,总结一下Ajax请求,与大家分享一下,希望能给学习Ajax的同学一些帮助,废话不多手,直接开始~~~ ...

  2. 测试工具——JMeter

    本学期新学的课程,软件测试,上机的实验用到了C++Test,QTP,还有JMeter.今天针对JMeter做一次总结,方便以后用到,知道步骤会更加方便. 首先,对Jmeter进行一个大致的了解,包括对 ...

  3. 测评:华为最新移动应用/APP测试工具MobileTest

    一.目前移动应用/App的测试痛点及可选方案 移动互联网市场进入下半场,同质化竞争激烈,平均获客成本增加.屏幕不适配.闪退.无响应.UI异常等兼容性问题严重影响用户体验,影响用户转化率和用户粘性.如何 ...

  4. 【JAVAWEB学习笔记】网上商城实战2:异步加载分类、Redis缓存分类和显示商品

    网上商城实战2 今日任务 完成分类模块的功能 完成商品模块的功能 1.1      分类模块的功能: 1.1.1    查询分类的功能: 1.1.2    查询分类的代码实现: 1.1.2.1  创建 ...

  5. 跟着刚哥深入学maven

    前言:目前所有的项目都在使用maven,可是一直没有时间去整理学习,这两天正好有时间,好好的整理一下. 一.为什么使用Maven这样的构建工具[why] ① 一个项目就是一个工程 如果项目非常庞大,就 ...

  6. (转)关于 Java 对象序列化您不知道的 5 件事

    关于 Java 对象序列化您不知道的 5 件事 转自:http://developer.51cto.com/art/201506/479979.htm 数年前,当和一个软件团队一起用 Java 语言编 ...

  7. python http长连接客户端

    背景: 线上机器,需要过滤access日志,发送给另外一个api 期初是单进程,效率太低,改为多进程发送后,查看日志中偶尔会出现异常错误(忘记截图了...) 总之就是端口不够用了报错 原因: 每一条日 ...

  8. 关于前后端同构,我的一点思路和心得(vue、nodejs、react、模版、amd)

    最近1年多,前后端同构慢慢变成一个流行词,也许很多人还停留在前后端分离的最佳实践道路上,但实际上又有一批人已经从简单的服务端渲染走向探索最佳前后端同构方案的路上了.不过,我只是膜拜后者的过客. 虽然大 ...

  9. 软件开发项目云端All-In-One体验

    如今在软件开发圈里混,Agile,DevOps,Cloud是大家经常挂在嘴边的词,其实大家各自都有在应用层上的经验,但是如何把三者很好的结合起来,这是所有项目管理者困惑和需要的问题. Agile让我们 ...

  10. IBM芯片新功能:诊断癌症

    治愈任何疾病的最好方法是什么?-------------- 当然是把它扼杀在摇篮里. "早发现早治疗"已经是老生常谈,但要准确监测疾病又谈何容易?不过现在,IBM这枚小小的芯片就能 ...