SPA(单页面富应用single page web application)在开发环境中依赖node和npm运行,项目在开发完毕后,需要进行配置生产环境进行打包,然后部署到服务器上方可发布。
1.分析webpack打包后的产物
SPA项目中,只有一个.html文件,其余都是静态资源
。实际部署到生产环境时,一般会将html挂在后端程序下,由后端路由渲染这个页面,将所有的静态资源(css、js、image、iconfont等)单独由部署到CDN,当然也可以也可以和后端程序放在一起,以实现前后端分离。
在webpack.config.js中,我们指定了output选项的配置:
output: {
path: path.join(__dirname, './dist'),
publicPath: '/dist/',
filename: 'index.js'
}
那么,在生产环境打包完成后,所有的资源都会放在zhihu-daily/dist这个文件夹下。
2.安装使用到的依赖
打包会用到webpack-merge:主要用于文件合并
、html-webpack-plugin:通过模板渲染html文件
这两个依赖,通过npm安装:
npm install --save-dev webpack-merge html-webpack-plugin
3.新建生产环境配置文件
为了方便开发环境和生产环境的切换,我们在根目录下新建一个用于配置生产环境的配置文件webpack.prod.config.js,代码如下:
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var merge = require('webpack-merge');
var webpackBaseConfig = require('./webpack.config.js');
// 清空配置文件的插件列表
webpackBaseConfig.plugins = [];
module.exports = merge(webpackBaseConfig, {
output: {
publicPath: '/dist/',
// 将入口文件重命名为带有20位hash值的唯一文件
filename: '[name].[hash].js'
},
plugins: [
new ExtractTextPlugin({
// 提取css,将文件命名为带有20位hash值的唯一文件
filename: '[name].[hash].css',
allChunks: true
}),
// 定义当前node环境为生产环境
new webpack.DefinePlugin({
'procee.env': {
NODE_ENV: '"production"'
}
}),
// 压缩js
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
}
}),
// 提取模板并在根目录下生成入口html文件(zhihu-daily/index_prod.html,zhihu-daily/dist/..)
new HtmlWebpackPlugin({
filename: '../index_prod.html',
template: './index.ejs',
inject: false
})
]
})
webpack.prod.config.js主要起到以下作用:
- 使用
webpack-merge
在webpack.config.js的基础上扩展部分参数为生产环境,如:清空插件列表、输出带有20位hash值的css、js文件、定义当前环境、压缩js等。 -
html-webpack-plugin
用来生产html文件,通过它的template选项指定模板为根目录下的index.ejs
,然后输出到filename指定的目录,即zhihu-daily/index_prod.html。其中,模板index.ejs动态设置了静态资源的路径和文件名。
4.新建模板文件
在webpack.prod.config.js里,我们用到了:
new HtmlWebpackPlugin({
filename: '../index_prod.html',
template: './index.ejs',
inject: false
})
在根目录下新建index.ejs,这个文件是用来作为模板,根据配置最终输出index_prod.html
。代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="<%= htmlWebpackPlugin.files.css[0] %>">
</head>
<body>
<div id="app"></div>
<script src="<%= htmlWebpackPlugin.files.js[0] %>"></script>
</body>
</html>
为何要设置动态的路径和文件名?
静态资源在大部分场景下都有缓存(304),更新上线后都希望用户能及时看到最新的内容,所以给打包后的css和js文件的名称都加了20位的hash值,这样打包后的文件名就是唯一的了,如:main.1cbc192f6ebd984a9dd0.css,只要不对html文件设置缓存,上线立即就可以加载到最新的静态资源。
5.配置打包shell命令
完成3,4两步后,我们需要配置一下shell命令以便webpack.prod.config.js生效,在package.json
中的scripts
属性下加入build
属性,以下代码:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --open --host 0.0.0.0 --port 8888 --config webpack.config.js",
"build": "webpack --progress --hide-modules --config webpack.prod.config.js"
}
然后在终端内运行npm run build
,等待打包完成,会在根目录下生成一个包含所有静态资源的dist文件夹和入口文件index_prod.html。打包过程如下:
这就代表打包成功,根目录下的index_prod.html和dist文件夹就是我们生产环境的打包文件。
6.直接在磁盘中访问index_prod.html
在资源管理器中找到index_prod.html,在浏览器中打开,发现什么也没有。打开控制台报错:
说明html文件没有找到相应的静态资源,原因是在index_prod.html中使用了
/dist/main.xxxx.css、/dist/main.xxxx.js
引永静态资源,直接在磁盘中打开并不能找到这个路径,把/dist
替换成dist
即可。效果如下:image.png
不过在大部分情况下,我们都是将打包后的文件部署到tomcat上,这个路径根据实际需求进行修改即可。
至此,我们完成了一个简单的生产环境打包示例。
完整代码github地址:https://github.com/zhiyuanMain/zhihu-daily
网友评论