基于react-app、webpack4一步步搭建可生产的react框架****demo有详细翻译注释说明****
文章供未搭建过生产环境框架的朋友学习,不严谨处望大佬指正
Hello 小伙伴们,首先问一下你们有自己搭过react框架嘛?
我好像听到了你们说:of course, react-app
是的说到搭建框架,现在基本都是用的脚手架,简单、快速、高效的脚手架提供给我们的只是通常最基础的一些配套设备,对于我们自己写写demo的话甚至不需要对脚手架进行改动,也就更不会改webpack的配套文件了。
然而
但如果应用到生产环境,我们需要自定义配置一些webpack的功能的话,脚手架提供的显然就不够了,这时候我们就该考虑对脚手架里的webpack "开刀" 了,接下看我们就来对webpack做一场 "手术"。
第一步搭建react-app
现在市面上的脚手架有好几种
我用官网推荐的最新脚手架一行代码搞定
npm init react-app my-app //npm
yarn create react-app my-app //yarn
安装好之后项目目录结构就是这样
剥离react-scripts文件
细心的小伙伴会发现,package.json配置文件里的包很少,运行命令都是react-scripts开头,那么我们就去node_modules里找找这个react-script文件,看看它究竟是何方神圣。
剩下的我们交给ctrl+c 和 ctrl+v
由于这两个文件被剥离出来,我们命令就不能引用react-scripts里的脚本,而是我们剥离后的,所以package.json也得跟着修改
package.json依赖跟着改
test和eject都是部署自动化测试的我们先不看,只留下打包和运行,习惯vue的dev命令小伙伴还可以加个dev命令,然后我们运行一下
哦吼,报错了,什么原因呢,原来是我们把两文件拿出来, 相关的依赖没有安装,于是我们去react-scripts里的package.json里,把dependencies里需要的依赖复制出来放到最外面的package.json里
执行命令,安装一波依赖包,二选一
npm install
yarn install
我们再次运行一下看看 yarn dev
嗯我们熟悉的它又回来了,严谨点我们再执行yarn build
到这里说明我们剥离阶段已经完成,这样还不能用于生产,接下来我们在config和scripts文件做写文章,顺带着解读整个webpack
生产分环境打包应用场景
正常开发项目,在发布正式之前,一般都会有个测试环境,如果我们只打一个包用于正式和测试使用,有时候就会很尴尬,尤其是公司配置了自动发布的时候,并不知道你这个包是想发布正式还测试,这时候能按照我需求能分别打包出正式和测试包就很nice了,
目标:根据命令行打包出正式或者测试两种包
思考:一个命令要想打出两个包,说明webpack出口文件肯定得有两个
行动一、那我们就找到webpack.config.js文件,找到output
这里的出口文件是paths.appBuild的,我们继续找paths这个变量
发现是一个引用,找到我们去看看这个paths文件
行动二、我们继续找paths.js
顾名思义,这个文件就是所有打包编译路径文件,这里的appBuild就是打包文件名可以自由配置,那么我们就在build目录下进行判断再生成两个环境的包 思考:我们想搞事情的话就只能在,paths和output之间 因为变量是可以更改的,所以我们重新回到webpack.config.js,对paths进行处理
行动三、回到wabpack修改一波paths
我们可以看到整个webpack.config.js导出时候接受了一个环境变量,这不正是我们需要的吗,那我们paths.appBuild = build/动态环境变量,是不是就能根据环境生成两个文件夹了
做好这些,剩下的问题就是webpackEnv是从哪来的?在哪传参的?
行动四、找到webpack方法引用和传参
找啊找,又用一个月终于在,scripts/build.js找到了webpack引用
这里就是环境变量的传参了,可以看到原来这里写死了
思考:只要我们能动态的传递环境变量,就能根据变量生成不同的包
行动五、动态添加环境变量
行动六、打包试试结果如何
我们来试试yarn build,输入打包命令时候手动选择环境
这不就是我们想要的吗,选择测试和正式分别打包试试
嗯哼,完美!
优化—打包时生成带CDN链接的index.html
项目中为了提升用户体验,少不了使用cdn
方法一、使用模板引擎+node,动态引入打包好的文件路径
但这样还需要单独开启一个node服务,将所有路由都过滤一次统一走模板引擎,在不做SEO的情况下太浪费
方法二、webpack的插件'html-webpack-plugin'、'webpack-manifest-plugin'了解一下
感兴趣的可以去深入研究一下
这两个插件,会自动生成一个'asset-manifest.json'文件,将打包的文件路径都存在里面,并动态的生成html标签, 使用cdn的话,打包后上传打包文件,publicPath:cdn路径前缀就可以了
优化—打包时上传静态资源
上传操作,直接写在build.js的打包结束后执行
//config = await configFactory( env)
config = await configFactory( env, `${Domain}${Const.projectName}` );
之前这个方法我们传了一个env给webpack,上传静态资源后我们可以将cdn前缀传过去,'webpack-manifest-plugin'当成这个插件的publicPath:路径
//模拟上传操作
//************上传操作可以在这里写************* */
await startUploadImage( env, 'token', 'qiniu' )
await startUpload( env, 'token', 'qiniu' )
//************上传操作可以在这里写************* */
/**
* @desc 上传静态js/css资源
* @param {string} env 环境变量
* @param {string} token
*
*/
async function startUpload( env, token, qiniu ) {
const files = glob.sync( `${paths.appBuild}/static/{js,css}/**/*.{js,css}` )
if ( files.length === 0 ) throw new Error( '请先build环境静态资源' )
for ( let filepath of files ) {
const fileExtension = filepath.substring( filepath.lastIndexOf( '.' ) + 1 )
// 文件上传
console.log( colors.underline( filepath ) )
console.log( colors.magenta( `${ Const["domain"][env]+'static/'+fileExtension +'/'+ path.basename(filepath)}` ) )
}
}
/**
* @desc 上传静态图片资源
* @param {string} env
* @param {string} token
*
*/
async function startUploadImage( env, token, qiniu ) {
const files = glob.sync( `${paths.appBuild}/static/media/**/*.{png,jpg,gif,jpeg,svg}` )
for ( let filepath of files ) {
// 文件上传
console.log( colors.underline( filepath ) )
console.log( colors.magenta( `${ Const["domain"][env]+'static/media/' + path.basename(filepath)}` ) )
}
}
yarn build 看下执行效果
CSDN博客 、 掘金 ,搜索:@baby张 更多专栏技术文章