背景
在react项目中, 通常会用Webpack去打包应用, 随着项目越来越庞大,打包后的文件也会变得越来越大,前端资源来说,文件体积过大是很影响性能的一项,会导致首次加载过长的时间,因此很多只有 在特定环境下才需要的代码,一开始就加载进来是不合理的,所以我们得按需加载这些资源。 为了实现这种需要,我们则需要做代码拆分。
wepack 代码拆分的实现方式
有三种常用的代码分离方法:
- 入口起点(entry points):使用
entry
配置手动地分离代码。 - 防止重复(prevent duplication):使用
SplitChunks
去重和分离 chunk。 - 动态导入(dynamic imports) :通过模块的内联函数调用来分离代码。
这里主要描述第三种Dynamic Import
:动态加载
当涉及到动态代码拆分时,webpack 提供了两个类似的技术。对于动态导入,第一种,也是推荐选择的方式是,使用符合 ECMAScript 提案 的 import()
语法。第二种,则是使用 webpack 特定的 require.ensure
。
import()
调用会在内部用到 promises
webpack.config.js
const path = require('path');
module.exports = {
mode: 'development',
entry: {
index: './src/index.js'
},
output: {
filename: '[name].bundle.js',
chunkFilename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
chunkFilename
: 它决定非入口 chunk 的名称
coding
function getComponent() {
return import(/* webpackChunkName: "lodash" */ 'lodash').then(_ => {
var element = document.createElement('div');
var _ = _.default;
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}).catch(error => 'An error occurred while loading the component');
}
getComponent().then(component => {
document.body.appendChild(component);
})
webpackChunkName
: 这样做会导致我们的 bundle 被命名为lodash.bundle.js
,默认[id].bundle.js
。想了解更多关于webpackChunkName
和其他可用选项,请查看import()
相关文档。
react 异步组件
基本异步组件设计
有两个组件,一个组件是import的组件,另一个是渲染组件
1.同步写法
import Bar from './components/Bar';
class Foo extends React.Component {
render() {
return <Bar/>;
}
}
2.异步写法
class MyComponent extends React.Component {
state = {
Bar: null
};
componentWillMount() {
import('./components/Bar').then(Bar => {
this.setState({ Bar });
})).catch((error) => {
console.log('error', error);
});;
}
render() {
let {Bar} = this.state;
if (!Bar) {
return <div>Loading...</div>;
} else {
return <Bar/>;
};
}
}
这是一整个工作流程,跟异步请求api一样,我们需要处理一系列的特殊需求。
- loading 组件(自定义)
- 组件加载异常之后需要给出提示,让用户重新load
- loading闪烁问题,(如果组件加载的十分快,则不需要用loading)
4.处理loader超时,网络连接断开或者失败,或者永久性挂起时
此外我们根据业务场景,还可以有一些其他需求
1.自定义渲染: 渲染default
导出的组件,可以自定义封装导出组件
2.加载多个资源:同时导入多个组件
3.预加载
4.服务端支持
以上功能需求我们可以自己coding,当然FEE社区以及为我们提供比较成熟的解决方案
react-router 官方说明
webpack,babel-plugin-syntax-dynamic-import
,react-loadable
来完成这个操作。
webpack 内置了 dynamic imports;然而,如果你正使用 Babel (例如:将 JSX 编译成 JavaScript) 那么你将需要使用 babel-plugin-syntax-dynamic-import
插件。它仅仅是一个语法插件,也就是说 Babel 不会做任何额外的转换。它仅仅允许 Babel 从语法上分析动态导入,所以 webpack 可以将它们拆分打包。
{
"presets": [
"react"
],
"plugins": [
"syntax-dynamic-import"
]
}
import Loadable from 'react-loadable';
import Loading from './Loading';
const LoadableComponent = Loadable({
loader: () => import('./Dashboard'),
loading: Loading,
})
export default class LoadableDashboard extends React.Component {
render() {
return <LoadableComponent />;
}
}
网友评论