记一次fis3+react开发经历
前言:虽然说是记录fis3+react的一次开发经历。但是在项目的上线前几天收到公司TC委员会的邮件,因为react的开源协议让找到react的替代方案,并且逐步下线线上的react项目。真的是可以用“出师未捷身先死”来形容这次开发了。 不过经过调研以后发现在业界已经有了一些开源方案来替代react 。最有名的就是preact的了吧。而且按照官网的方案来做迁移的话,迁移的成本也挺小的。后续会介绍下迁移的情况。本文也是主要介绍下,使用react+fis3开发的一些经验和其中遇到的问题的解决方案。 下面的文章也统一用 1.为什么要使用react+fis3目前在选择使用
按照业内主流做法使用react搭配webpack是最主流的。但是在公司内主推fis3的情况下还是选择了fis3。而且fi3的维护团队也产出过一篇引导文章和demo来介绍使用fi3开发react应用(参考文章见文章末尾)。 在项目开始前也在分析要不要引入 2.项目的目录结构和作用react的开发模式基本上都差不多。因为这次我并没有引入 . ├── components //组件目录 ├── containers //组件容器 ├── language //语言包目录,为项目做国际化预留的能力 ├── node_modules //npm依赖 ├── package-lock.json ├── package.json ├── page //页面模块 ├── routes //路由模块 ├── state //因为没有引入redux但是有一个页面的状态实在太多还是单独为它做了一个文件管理state ├── static //静态文件模块 └── yarn.lock 3.拆分页面使用react的第一项工作就是要拆分自己页面。把自己的页面拆分成“一块一块”
我是这样拆分我的页面的,红色的线就是我的拆分模式。
所以我的 ├── components │ ├── Header.jsx │ ├── Input.jsx │ ├── PassBtn.jsx │ ├── SafeCenter.jsx │ ├── SafeList.jsx │ ├── header.styl │ ├── input.styl │ ├── passbtn.styl │ ├── safecenter.styl │ └── safelist.styl 而我的 ├── containers │ ├── BankList.jsx │ ├── EditUserInfor.jsx │ ├── EditUserInfor.styl │ ├── SafeCenterIndex.jsx │ ├── VerifyBank.jsx │ ├── VerifyRealName.jsx │ ├── banklist.styl │ ├── verifybank.styl │ └── verifyrealname.styl 还有最有一个值得介绍的就是 ├── routes │ └── index.jsx 因为使用的 export default ( <Router history={createBrowserHistory()} > <SafeCenterIndex path="/v4/security/"/> <VerifyRealName path="/v4/security/verifyname"/> <VerifyBank path="/v4/security/verifybank"/> </Router> ); 4.写react肯定会面临的问题写react时,我们在享受着react的visual dom的高性能和不依赖dom的编程的便利时,面对最大的问题就是对组件的 我先来举个简单的例子。我们有以下一个对像来管理页面的显示状态: var obj= { "aaa": { "bbb": { "ccc": { "ddd": { "header": "istrue" } } } } } 当我们的一个 obj.aaa.bbb.ccc.ddd.header='isfalse'; 有时候我们为了能够让代码更健壮可能会这么写: obj.aaa || obj.aaa.bbb || obj.aaa.bbb.ccc || obj.aaa.bbb.ccc.ddd || obj.aaa.bbb.ccc.ddd.header = 'isfalse' 会发现这样做真的繁琐。当然我在做的时候也面临着这样的问题。通过查询相关资料,最佳的解决方案当然还是引入 这三个库中文分析介绍的文档挺多的可以自行搜索了解。当然最后我上面的都没有用。因为之前的我的项目中已经引入了 如果使用lodash更新上面header的值,写法如下: import * as _ form 'lodash'; _.set(obj,'aaa.bbb.ccc.ddd.header','isfalse'); //更新header的值 var header = _.get(obj,'aaa.bbb.ccc.ddd.header') //获取header的值 还有一个值得注意的地方就是在我们更新 当然使用 import * as _ form 'lodash'; var initState = {}; var deepCloneState = _.cloneDeep(initState); // 我们操作的其实都是这个clone的备份 第三个,出现的比较坑的问题。浏览器或者是webview缓存 这个问题主要发生在需要多次以 axios.get('/v4/xxx/action?v=' + (new Date).getTime()) .then(data => {}) .catch(err => {}) 5.打包工具的配置本来想统一的使用 // 定义一个全局的变量目录 const dirList = '{actions,components,constants,routes,containers,page,state,language,reducers,store}'; fis.match('/client/(' + dirList + '/**.{js,es,jsx,ts,tsx})',{ parser: fis.plugin('babel-5.x',{ sourceMaps: false,optional: ['es7.decorators','es7.classProperties'],jsxPragma: 'h' // 这里也是最重要的迁移preact后必须加的一个参数 }),// 页面中显示的url并且加上自定义的v4前缀 url: '/v4${static}/${namespace}/$1$2$3$4$5$6$7$8$9$10',isJsXLike: true,// 设置位模块目录最后的编译结果都是会用define包裹 isMod: true }) // 这里都是为了给静态文件加上v4自定义前缀 .match('/client/({components,containers}/**.styl)',{ url: '/v4${static}/${namespace}/$1',}) // 这里都是为了给静态文件加上v4自定义前缀 .match('/client/static/({img,js,styl}/**.{png,ico,styl})',{ url: '/v4${static}/${namespace}/static/$1$2$3' }) // 因为使用的stylus做位css的预编译工具,这里的配置是编译stylus的配置 .match('*.styl',{ rExt: '.css',parser: fis.plugin('stylus',{ sourcemap: false }),preprocessor: fis.plugin('autoprefixer',{ 'browsers': ['Android >= 2.1','iOS >= 4','ie >= 8','firefox >= 15'],'cascade': false }) }) 以上的配置文件是开发环境的配置,在页面加载的时候也是对静态文件逐条加载的。
而且页面的加载时间也比较长不符合我们线上的加载静态文件的需求。
紧接着对打包脚本进行优化 fis.media('prod') // 压缩css .match('*.{styl,css}',{ 'useHash': true,'optimizer': fis.plugin('clean-css') }) .match('/client/node_modules/**.{js,jsx}',{ 'isMod': true }) .match('/client/**.{js,tsx}',{ 'preprocessor': [ fis.plugin('js-require-file'),fis.plugin('js-require-css') ] }) //合并静态文件 .match('::packager',{ 'packager': fis.plugin('deps-pack',{ // 将所有的npm依赖打包成一个文件 '/client/pkg/npm/bundle.js': [ '/client/page/index.js:deps','!/client/' + dirList + '/**' ],//将所有的业务代码打包成一个文件 '/client/pkg/npm/index.js': [ '/client/page/index.js','/client/page/index.js:deps' ],//将所有的css文件打包成一个文件 '/client/pkg/npm/bundle.css': [ '/client/**.{styl,'!/client/static/**.{styl,css}' ] }) }) //给所有打包完的文件加前缀 .match('/client/(pkg/npm/**.{js,css})',{ 'url': '/v4${static}/${namespace}/$1',}); 这样做最后线上的页面加载时,加载的静态文件(除了图片)只有3个。页面的加载时间也保留在 排除非首屏的加载,使用缓存加载页面的。这个时间已经缩短的极小了。
以下是我在一APP内打开页面后,每次都使用缓存文件加载的结果。所有的静态文件都使用了本地缓存,http状态码都是304。
在这个过程中也发现一个问题,就是使用时间戳的方式和使用hash戳的方式,缓存静态文件。观察下面的截图发现,使用时间戳的方式,并不能有效的缓存我们的静态文件,每次进入页面,静态文件都重新发起了请求。因为又没有使用CDN加速,这样其实也间接的对我们的服务器造成压力。
迁移preact最后就是介绍下迁移react到preact我都是做了那些工作吧。当然按照官网提供的步骤一步一步走肯定是没有错的。 首先是修改库的引入方式 import {h,render,Component} from 'preact'; 因为使用了 import {h,Component} from 'preact'; import {Router} from 'preact-router'; // import {Router} from 'react-router'; import SafeCenterIndex from '../containers/SafeCenterIndex'; import VerifyRealName from '../containers/VerifyRealName'; import VerifyBank from '../containers/VerifyBank'; import {createBrowserHistory} from 'history'; export default ( //这里的写法和react-router不一样。 <Router history={createBrowserHistory()} > <SafeCenterIndex path="/v4/security/"/> <VerifyRealName path="/v4/security/verifyname"/> <VerifyBank path="/v4/security/verifybank"/> </Router> ); 第二就是修改编译的打包脚本。按照官网的介绍就是要修改最后编译结果的jsx的包裹方式。在前面的关于打包脚本的配置已经介绍过了.主要就是配置 fis.match('/client/(' + dirList + '/**.{js,jsxPragma: 'h' }),url: '/v4${static}/${namespace}/$1$2$3$4$5$6$7$8$9$10',isMod: true }) 后续的计划
参考文章:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |