webpack 多页面构建
目标:
- 基于webpack支持react多页面构建(不用gulp,gulp-webpack 构建速度太慢[3]), generator-react-webpack 对单页面支持很好,但对多页面,需要改造
- 提高开发人员的效率
- 并能对项目进行足够的性能优化
- 提高构建的效率
配置文件编写(webpack.config.js)
示例:
1 | var path = require('path'); |
Webpack的配置主要包括以下几大项目:
entry:js入口源文件
- 为了使用多入口文件,你可以给entry传入一个对象。对象的key代表入口点名字,value代表入口点。当使用多入口点的时候,需要重载output.filename,否责每个入口点都写入到同一个输出文件里面了。使用[name]来得到入口点名字。
例子:
{ entry: { a: "./a", b: "./b", //支持数组形式,将加载数组中的所有模块,但以最后一个模块作为输出 //该方法可以添加多个彼此不互相依赖的文件 c: ["./c", "./d"] }, output: { path: path.join(__dirname, "dist"), filename: "[name].entry.js" // a.enrty.js, b.enrty.js, c.entry.js } }
output:生成文件
output参数是个对象,定义了输出文件的位置及名字.
例子:
output: { path: "dist/js/page", publicPath: "/output/", filename: "[name].bundle.js" } path: 打包文件存放的绝对路径 publicPath: 网站运行时的访问路径 filename:打包后的文件名
module:模块加载器
在webpack中JavaScript,CSS,LESS,TypeScript,JSX,CoffeeScript,图片等静态文件都是模块,不同模块的加载是通过模块加载器(webpack-loader)来统一管理的。loaders之间是可以串联的,一个加载器的输出可以作为下一个加载器的输入,最终返回到JavaScript上。
例子:
module: { //加载器配置 loaders: [ //.css 文件使用 style-loader 和 css-loader 来处理 { test: /\.css$/, loader: 'style-loader!css-loader' }, //.js 文件使用 jsx-loader 来编译处理 { test: /\.js$/, loader: 'jsx-loader?harmony' }, //.scss 文件使用 style-loader、css-loader 和 sass-loader 来编译处理 { test: /\.scss$/, loader: 'style!css!sass?sourceMap' }, //图片文件使用 url-loader 来处理,小于8kb的直接转为base64 { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' } ] }
多个loader可以用在同一个文件上并且被链式调用。链式调用时从右到左执行且loader之间用“!”来分割。
- 模块加载器(loader)自身可以根据传入不同的参数进行配置。
resolve:文件路径的指向
webpack在构建包的时候会按目录的进行文件的查找,resolve属性中的extensions数组中用于配置程序可以自行补全哪些文件后缀:
例子:
resolve: { //查找module的话从这里开始查找 root: '/pomy/github/flux-example/src', //绝对路径 //自动扩展文件后缀名,意味着我们require模块可以省略不写后缀名 extensions: ['', '.js', '.json', '.scss'], //模块别名定义,方便后续直接引用别名,无须多写长长的地址 alias: { AppStore : 'js/stores/AppStores.js',//后续直接 require('AppStore') 即可 ActionType : 'js/actions/ActionType.js', AppAction : 'js/actions/AppAction.js' } }
plugins:插件,比loader更强大,能使用更多webpack的api
插件一般都是用于输出bundle的node模块。例如,uglifyJSPlugin获取bundle.js然后压缩和混淆内容以减小文件体积。类似的extract-text-webpack-plugin内部使用css-loader和style-loader来收集所有的css到一个地方最终将结果提取结果到一个独立的”styles.css“文件,并且在html里边引用style.css文件。
var ExtractTextPlugin = require("extract-text-webpack-plugin"); module: { loaders: [ { test: /\.css$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader") }, { test: /\.less$/, loader: ExtractTextPlugin.extract("style-loader", "css-loader!less-loader") } ] }, plugins: [ new ExtractTextPlugin("[name].css") ]
code-splitting 插件CommonsChunkPlugin
将多次引用的模块单独打包
new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', filename: isProduction ? 'js/vendor.[hash:8].js':'js/vendor.js', minChunks: 3 // 提取使用3次以上的模块,打包到vendor里 })
多页面 html 生成插件 html-webpack-plugin
例子:
var HtmlWebpackPlugin = require('html-webpack-plugin'); chunks.forEach(function(pathname) { if (pathname == 'vendor') { return; } var conf = { title: 'My App', filename: isProduction? '../view/' + pathname + '.html' : pathname + '.html', template: './src/template.html', inject: 'body', minify: { removeComments: true, collapseWhitespace: false } }; if (pathname in module.exports.entry) { conf.chunks = ['vendor', pathname]; conf.hash = false; } module.exports.plugins.push(new HtmlWebpackPlugin(conf)); });
* src目录下有个template.html文件,无需引入任何css和js,webpack会自动帮我们打包引入,`<%= htmlWebpackPlugin.options.title %>`读取配置好的页面标题
1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title> <%= htmlWebpackPlugin.options.title %> </title>
</head>
<body>
<div id="app"></div>
</body>
</html>
* 最终通过打包,会生成对应入口的html文件,
比如src/view/index/index.js会生成view/index/index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> My App </title>
<link href="/dist/css/vendor.abf9657f.css" rel="stylesheet">
<link href="/dist/css/index/index.abf9657f.css" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src="/dist/js/vendor.abf9657f.js"></script>
<script type="text/javascript" src="/dist/js/index/index.abf9657f.js"></script>
</body>
</html>
* 你会发现相关资源文件都自动引入了,十分便捷。
webpack 常用命令
- webpack 最基本的启动webpack命令
- webpack -w 提供watch方法,实时进行打包更新
- webpack -p 对打包后的文件进行压缩
- webpack -d 提供SourceMaps,方便调试
- webpack –colors 输出结果带彩色,比如:会用红色显示耗时较长的步骤
- webpack –profile 输出性能数据,可以看到每一步的耗时
- webpack –display-modules 默认情况下 node_modules 下的模块会被隐藏,加上这个参数可以显示这些被隐藏的模块
webpack dev server
配置示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config.js');
for (var i in config.entry) {
// 每个入口文件加入 client websocket 热加载脚本
config.entry[i].unshift(
"webpack-dev-server/client?http://127.0.0.1:3000/",
"webpack/hot/only-dev-server"
);
}
config.module.loaders.unshift({
test: /\.jsx?$/,
loader: 'react-hot',
exclude: /node_modules/
});
config.plugins.push(new webpack.HotModuleReplacementPlugin());
new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
historyApiFallback: true,
stats: { colors: true }
}).listen(3000, '127.0.0.1', function (err, result) {
if (err) {
console.log(err);
}
console.log('server start');
});用处
- 开启服务器调试环境
- 解决以下两个问题:
- webpack –watch 打包速度慢
- 不能做到hot replace
配置
Content Base
- 如果不进行设定的话,服务器伺服默认是在当前目录下。
- 命令行设置
webpack-dev-server --content-base build/
webpack 配置
devServer: { contentBase: './src/', historyApiFallback: true, hot: true, port: defaultSettings.port, publicPath: '/assets/', noInfo: false }
publicPath
- webpack server 伺服的 bundle 是在内存中的,其相对路径由 publicPath 字段指定。
- 如果用以上的配置,bundle 可以通过地址 localhost:8080/assets/bundle.js 访问到。(注意:访问的不是output目录下的文件而是内存中的数据!)
自动更新和热替换
配置:
var config = require("./webpack.config.js"); config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080/", "webpack/hot/dev-server"); var compiler = webpack(config); var server = new webpackDevServer(compiler, { hot: true ... }); server.listen(8080);
关键配置:
config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080/", "webpack/hot/dev-server");
在每个入口文件注入 client websocket 热加载脚本。
参考文档:
webpack 多页面构建
- 使用 React 写个简单的活动页面运营系统
- Webpack+React多页面应用探索
- webpack不适合多页面应用?你写的插件还不够多
- 【AlloyTeam优化系列】构建篇
webpack react generator - generator-react-webpack
webpack 构建优化 - 开发工具心得:如何 10 倍提高你的 Webpack 构建效率
- webpack使用优化(基本篇)
- webpack使用优化(react篇)
webpack-dev-server - webpack-dev-server使用方法
- WEBPACK DEV SERVER
多入口以及code-splitting - webpack multiple-entry-points example
- MULTIPLE ENTRY POINTS
- CODE SPLITTING
webpack 配置 - 详解前端模块化工具-Webpack 不错的文章
- 【翻译】Webpack——令人困惑的地方好文章
webpack CommonsChunkPlugin详细教程 - webpack CommonsChunkPlugin详细教程