部署React+Redux Web App
http://www.hustlzp.com/post/2016/03/react-redux-deployment 前段时间使用React+Redux做了个后台管理的项目,在React初体验中分享了下入门经验。这篇文章谈谈我的部署实践。 目标怎样才是好的部署呢?我觉至少有以下2点:
代码层面首先从代码层面来分析。 使用React+Redux,往往会用到其强大的调试工具Redux DevTools。在手动配置DevTools时需要围绕Store、Component进行一些配置。然而这些都是用来方便调试的,生产环境下我们不希望加入这些东西,所以建议就是从代码上隔离development和production环境: containers/
Root.js
Root.dev.js
Root.prod.js
...
store/
index.js
store.dev.js
store.prod.js
同时采用单独的入口文件(比如上面的 if (process.env.NODE_ENV === 'production') { module.exports = require('./Root.prod'); } else { module.exports = require('./Root.dev'); } 有一个细节需要注意:ES6语法不支持在if中编写import,所以这里采用了CommonJS的模块引入方法 具体可以看看Redux的Real World示例项目。 代码层面还需要注意的一点就是按需import,否则可能会在打包时生成不必要的代码。 OK,我们现在用webpack打个包, 使用webpack打包别急,接下来我们来调教下打包工具。目前React主流打包工具有2种:webpack、Browserify。Browserify没用过,这里主要谈谈webpack的配置经验。 同上,建议为不同的环境准备不同的webpack配置文件,比如: devtools 文档在这里,我对source map技术不太了解,所以几个选项真不知道是干什么的。不过好在下面的表格中有写哪些是production supported,随便选择一个就好,感觉结果区别不大。这里我选择了
唔,这样好多了,把用于定位源码的source map分离出去了,一下子减少了一半以上的体积。(注:source map只会在浏览器devtools激活时加载,并不会影响正常的页面加载速度,具体可参考When is jQuery source map loaded?、JavaScript Source Map 详解。) plugins你可能会问“怎么不祭出UglifyJS啊?”,现在就祭...webpack文档中有一节Optimization,讲到了一些优化技巧。Chunks略高级没用过,看前面两个吧。提到了3个插件:UglifyJsPlugin、OccurenceOrderPlugin、DedupePlugin,第一个插件应该都懂是干啥,后面两个描述得挺高深的,不过不懂没关系,全用上试试,反正没副作用: plugins: [ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }),new webpack.optimize.DedupePlugin(),new webpack.optimize.OccurenceOrderPlugin() ] 打包结果:1.04 MB。 不要忽视NODE_ENV NODE_ENV其实就是一个环境变量,在Node中可以通过 React提供了2个版本的代码(见:Development vs. Production Builds): We provide two versions of React: an uncompressed version for development and a minified version for production. The development version includes extra warnings about common mistakes,whereas the production version includes extra performance optimizations and strips all error messages. 同时在React文档中明确建议在生产环境下设置 Note: by default,React will be in development mode. To use React in production mode,set the environment variable NODE_ENV to production (using envify or webpack's DefinePlugin). A minifier that performs dead-code elimination such as UglifyJS is recommended to completely remove the extra code present in development mode. 可以通过webpack的DefinePlugin设置环境变量,如下: plugins: [ ... new webpack.DefinePlugin({ 'process.env.NODE_ENV': JSON.stringify('production') }),] 打包结果:844 KB。 OK,webpack到此为止,给出完整的 var path = require('path'); var webpack = require('webpack'); module.exports = { devtool: 'source-map',entry: [ './index.js' ],output: { path: path.join(__dirname,'webpack-output'),filename: 'bundle.js',publicPath: '/webpack-output/' },plugins: [ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }),new webpack.optimize.OccurenceOrderPlugin(),new webpack.DefinePlugin({ 'production') }),],module: { loaders: [ { test: /.js$/,loader: 'babel',exclude: /node_modules/,include: __dirname },{ test: /.css$/,loaders: ["style",68);">"css"] },38);">/.scss$/,68);">"css",68);">"sass"] } ] },}; 打包结果存放在 使用FIS3添加hash前端公认的Best Practice就是给资源打上hash标签,这对缓存前端资源很有用。webpack文档中有一节Long-term Caching就是专门讲整的,然而配置起来好麻烦的样子,最后我还是选择了百度的FIS3做hash。 使用方法见文档,写的很详细。贴一下我的 // 需要打包的文件 fis.set('project.files',['index.html',68);">'static/**',68);">'webpack-output/**']); // 压缩CSS fis.match('*.css',{ optimizer: fis.plugin('clean-css') }); // 压缩PNG图片 fis.match('*.png',68);">'png-compressor') }); fis.match('*.{js,css,png}',{ useHash: true,//启用has domain: 'http://7xrdyx.com1.z0.glb.clouddn.com',136);font-style:italic;">// 添加CDN前缀 }); 其中,通过 运行
使用CDN844 KB虽然比最开始的8.4 M缩小到了1/10,但其实也很吓人。包大小基本上已经压缩到极限了,但我们还可以通过CDN来加快页面加载时间。 我选择的是七牛,效果不错,而且免费额度够用。 上一步中我们已经用FIS3添加了七牛CDN的前缀,接下来就是上传打包文件了。手动上传太麻烦,七牛提供了一个用来批上传的命令行工具qrsync,具体用法见文档。 使用Fabric进行远程部署 部署的时候难免会涉及到登陆server执行部署命令,你可以手动操作,但我推荐还是用一些工具来做。这方面工具不少,选择顺手的就行,我因为之前有过Python开发经验,所以一直用Fabric,很好用。安装下python,然后安装包管理工具pip,然后 在项目文件下创建 # coding: utf-8 from fabric.api import run,env,cd def deploy(): env.host_string = "username@ip" with cd('/path/to/your/project'): run('git pull') run('npm install') run('webpack --progress --config webpack.config.prod.js') run('fis3 release -d ./output') run('qrsync qrsync.conf.json') 其中, 执行 Nginx收尾工作交给Nginx:
我的 server { listen 80; server_name yourdomain.com; root /path/to/your/project; location / { try_files $uri /index.html; } } 注:有童鞋可能奇怪为什么没有添加cache的配置,因为所有东西都上传到CDN了... 浏览器实际加载效果在Chrome调试工具下看。 禁止缓存:
可以看到bundle的最终大小为206KB,加载时间是118ms。 启用缓存: 效果还不错。 开发->部署流程从开发到部署的流程如下:
是不是很简单? 其他还有一些东西可以加进来:
具体就不展开了。 就写到这里,欢迎建议。 · EOF · (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |