在 3.1.x
之后的 qap-cli 版本,我们集成了代码热更新的 feature。默认的开关 hotreload 是打开的,开发者只需按照 demo
项目的 index.jsx
与 container.jsx
组织代码即可。具体来说,页面的渲染逻辑在 container.jsx
文件中写,并 export
出来,而在 index.jsx
中只做 render
操作,从而方便在开发环境中注入用于控制热更新的代码。
index.jsx
'use strict'; import { createElement, Component, render } from 'rax'; import Demo from './container'; render(<Demo />);
container.jsx
'use strict'; import { createElement, Component, render } from 'rax'; import { View, Text, Modal, Link, Env } from 'nuke'; class Demo extends Component { constructor(props) { super(props); } render() { return ( <View style={styles.container}> </View> ); } } export default Demo;
新项目
新版本的qap-cli,可以对代码进行 tree shaking,从而减小打包体积。
https://github.com/airbnb/javascript/issues/1365
qap-cli 默认会开启 webpack 的 tree shaking 功能对打包体积进行优化,这就要求开发者仅export必要模块,谨慎的使用export default语法 。
新初始化的项目,默认关闭了add-module-exports,从而在开发阶段提醒开发者是否使用了不规范的export,当然你可以通过设置 webapck['optimize-size']['webpack']:false
选择关闭tree shaking
检测 。
最终优化的结果是当一个模块仅仅被使用到部分方法的时,在打包阶段不会将整个模块打入module内部。其背后原理可以参考 今天,你升级Webpack2了吗,文档中不在赘述了。
老项目
对于老项目(使用旧版qap-cli)而言,如果希望使用新版的诸多feature。可以选择升级项目,当然如果选择不升级,新版的qap-cli对老项目也是完全兼容的。具体的升级过程如下:
1、安装最新版的qap-cli npm install -g qap-cli
2、在根目录增加qap.config.js,并设置配置,具体内容见 qap.config.js。
3、删除本地的webpack.config.js
、.babel.rc
、gulpfile.js
如果在qap.config.js
中没有定义entry或entry为{}
,qap-cli
会默认取符合src/pages/页面名称/index.jsx
规则的所有文件作为入口,这也是我们**推荐的页面管理方式**。
如果你的页面入口不符合上述规则,又不方便调整。也可以使用自定义entry的方式定义页面入口,以下是一个伪代码demo。
webpack:{ entry:{ index:[path.resolve(process.cwd(),'src/index/index.jsx')], ndex:[path.resolve(process.cwd(),'src/detail/index.jsx')] } }
新项目默认使用扁平输出,即所有pages目录下的页面跳转如src/pages/first/index.jsx
到src/pages/second/index.jsx
,只需通过qap:///second.js
即可完成。
执行qap package
可以查看build目录下的所有页面都被输出为扁平的结构。
qap.config.js
的打包配置感觉没有作用,和上次的大包结果一样?对external的修改和webpack字段修改都会改变打包体积。如果打包体积未变化,可能是触发了happypack(4.0.0-beta2)
的强缓存bug。通过随便修改一行代码,与上次打包时的文件内容有区别即可绕过。
对于有自定义配置需求的开发者,可以在qap.config.js
的webpack对象下增加hack
字段,并指向自己的webpack.config.js文件[绝对路径],实现webpack配置文件的更改。如下:需要注意的是自定义的配置文件会覆盖脚手架所有的默认配置。请保证webpack配置文件的正确性。
webpack:{ hack: { webpackPath: path.resolve(process.cwd(), 'webpack.config.js'), }, }
1、使用自定义配置无法获取到qap-cli最新的打包优化更新。
2、任何webpack相关配置问题都需要开发者自行解决 webpack官网
以下是一个自定义的webpack配置:
/** * warning: we really don't recommand use your own webpack config file to develop qap. * 1、Can not get & update the recent config. * 2、Any config issue or error is beyond our area. */ const path = require('path'); const RaxWebpackPlugin = require('rax-webpack-plugin'); const webpack = require('webpack'); const babelConfig = require('./babel.config'); const cwd = process.cwd(); const babelInclude = [path.resolve(cwd, 'src')]; /** * use process.env.NODE_EV to judge the development or producttion * qap debug : process.env.NODE_ENV = 'development' * qap package : process.env.NODE_ENV = 'producttion' */ module.exports = { target: 'web', devServer: { disableHostCheck: true, // ! this can't be changed }, entry: { index: './src/pages/index/index.jsx', }, output: { pathinfo: true, filename: '[name].js', publicPath: '/build/', // ! this can't be changed }, resolve: { modules: [path.join(cwd, 'src'), path.join(cwd, 'node_modules'), 'node_modules'], extensions: ['.js', '.json', '.jsx'], alias: { $components: path.resolve(__dirname, './src/components'), $pages: path.resolve(__dirname, './src/pages'), $util: path.resolve(__dirname, './src/util'), $root: path.resolve(__dirname, './src/'), $data: path.resolve(__dirname, './data/'), }, }, resolveLoader: {}, plugins: [ new RaxWebpackPlugin({ target: 'bundle', externalBuiltinModules: true, }), new webpack.NoEmitOnErrorsPlugin(), // show webpakc build progress new webpack.ProgressPlugin((percentage, msg) => { const stream = process.stderr; if (stream.isTTY && percentage < 0.98) { stream.cursorTo(0); stream.write(`? building ...${(percentage * 100).toFixed(2)}%`); stream.clearLine(1); } else if (percentage === 1) { console.log('webpack: bundle build is now finished.'); } }), ], externals: {}, module: { loaders: [ { test: /\.js|\.jsx?$/, exclude: /lodash/, include: babelInclude, loaders: [`${require.resolve('babel-loader')}?${JSON.stringify(babelConfig)}`], }, { test: /\.less$/, loaders: [require.resolve('stylesheet-loader'), require.resolve('less-loader')], }, ], }, };