主要技术栈
React,
React-redux,
React-router,
Typescript,
antd,
Immutable,
…
需求
因为项目是一个SPA页面,随着项目的不断迭代,入口文件逐渐增大(app.js),所以想减少入口文件的体积。
方案
方案一:
webpack(require.ensure)+ react-router
因为使用require.ensure需要足够深的文件层级并且在对应文件需要定义index.ts文件作为require.ensure入口,书写起来比较麻烦,而且相对于工作量来说也是大有增加(具体的实现方案网上也比较多),故没有选择。
方案二:
webpack(bundle-loader)+ react-router(lazyLoadComponent)
优势:
1、不用过多的文件层级,保持文件的prue。
2、不用自己定义require.ensure
安装bundle-loader
npm install bundle-loader --save-dev
webpack中加载loader(这里使用的是webpack2)
export default {
entry: entries,
output: {
path: __dirname,
filename: `${dist}/js/[name].js`, // 这里的dist是我定义的变量
publicPath: 'https://127.0.0.1/', // 这里很关键=>单独拿出来解释
},
resolve: {
extensions: [
'.js',
'.jsx',
'.ts',
'.tsx',
'.css',
'.less',
'.json',
'.gif',
'.html',
'.png',
'.webp',
'.jpg',
],
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
},
{
test: /\.(tsx|ts)/,
exclude: [
path.resolve(__dirname, "src/pages/")
],
loader: 'ts-loader',
},
{
test: /src\\pages(\\.*).(tsx|ts)/,
use: [
'bundle-loader?lazy',
'ts-loader',
],
},
{
test: /\.(less)?$/,
use: [
'style-loader',
'css-loader',
'less-loader',
],
// loader: 'style!css!less'
},
{
test: /.css$/,
loader: extractCSS.extract({
fallbackLoader: 'style-loader',
loader: 'css-loader',
}),
},
{
test: /\.(jpg|png|gif|jpeg)?$/,
loader: `url-loader?limit=20480&name=${dist}/images/[name].[hash:8].[ext]`,
},
{
test: /\.(eot|woff(2)?|ttf|svg)?(@.+)*$/,
loader: `url-loader?limit=20480&name=${dist}/other/[name].[hash:8].[ext]`,
}
],
},
plugins: [
/**
* DllReferencePlugin
*/
new DllReferencePlugin({
context: __dirname,
manifest,
}),
/**
* CommonsChunkPlugin
*/
new CommonsChunkPlugin({
name: 'common',
filename: `${dist}/common.js`,
minChunks: 2,
chunks: entriesKey
}),
],
devtool: 'cheap-module-source-map',
devServer: {
port,
https,
contentBase: ROOTPATH,
compress: true,
inline: true,
quiet: false,
stats: { colors: true },
watchOptions: {
aggregateTimeout: 300,
poll: true,
},
headers: {
'Access-Control-Allow-Origin': '*',
},
}
};
配置详解
{
test: /src\\pages(\\.*).(tsx|ts)/,
use: [
'bundle-loader?lazy',
'ts-loader',
],
},
test:是我写的正则用来匹配我需要异步加载的文件,并且使用use中的bundle-loader->ts-loader。
(ps:在ts-loader编译全局文件时,需要exclude[需要异步加载的路径])
route配置
// router.tsx
import * as EffectiveCustomer from './pages/wuyoubao/customerManagement/effectiveCustomer';
function lazyLoadComponent(lazyModule) {
return (location, cb) => {
lazyModule(module => cb(null, module.default));
}
}
<Router history={history}>
<Route path="/admindev/basic/common" {...this.props} {...routerProps}>
<IndexRoute getComponent={lazyLoadComponent(Index)}/>
<Route path="/api/wuyoubao/effective" getComponent={lazyLoadComponent(EffectiveCustomer)}/>
</Route>
</Router>
注意事项
因为router.tsx中引用的tsx全部是被bundle-loader编译的,而bundle-loader对ES6特性支持不是很好,比如:
ES6可以解析
import { OrderInfoMessage } from './fundConfirmCom/fundConfirmInfoOrder';
console.log(OrderInfoMessage)
// 可以解析
但是这种方式bundle-loader解析不了,它所能解析的方式:
bundle-loader解析module
import { OrderInfoMessage } from './fundConfirmCom/fundConfirmInfoOrder';
console.log(OrderInfoMessage) // undefined
// bundle-loader可以识别的方式:
import * as OrderInfoMessage from './fundConfirmCom/fundConfirmInfoOrder';
console.log(OrderInfoMessage) // 可以解析