@xiaoqq
2016-12-29T04:09:05.000000Z
字数 2931
阅读 1220
Webpack
目前项目中存在的问题:
需要实现的目标:
采用Webpack2.X的Lazy Loading
npm i webpack@2.1.0-beta.25 --save-dev
npm i webpack@2.1.0-beta.25 -g
参考文章:https://gold.xitu.io/entry/581d9fcc8ac247004ff3c70e
在现有的项目上直接使用webpack2.x会报错,必须先修改配置文件
1)resolve.extensions去掉' '
resolve: {
extensions: ['.js', '.jsx']
},
2)去掉new webpack.optimize.OccurenceOrderPlugin()
插件
3) (可选)对module进行改造
module: {
- loaders: [
+ rules: [
{
test: /\.css$/,
- loaders: [
+ use: [
{
loader: "style-loader"
},
{
loader: "css-loader",
- query: {
+ options: {
modules: true
}
]
}
]
}
参考:https://webpack.js.org/guides/migrating/
import React from 'react';
/**
* @function 支持异步加载的封装组件
*/
class LazilyLoad extends React.Component {
constructor() {
super(...arguments);
this.state = {
isLoaded: false,
};
}
componentWillMount() {
this.load(this.props);
}
componentDidMount() {
this._isMounted = true;
}
componentWillReceiveProps(next) {
if (next.modules === this.props.modules) return null;
this.load(next);
}
componentWillUnmount() {
this._isMounted = false;
}
load(props) {
this.setState({
isLoaded: false,
});
const {modules} = props;
const keys = Object.keys(modules);
Promise.all(keys.map((key) => modules[key]()))
.then((values) => (keys.reduce((agg, key, index) => {
agg[key] = values[index];
return agg;
}, {})))
.then((result) => {
if (!this._isMounted) return null;
this.setState({modules: result, isLoaded: true});
});
}
render() {
if (!this.state.isLoaded) return null;
return React.Children.only(this.props.children(this.state.modules));
}
}
LazilyLoad.propTypes = {
children: React.PropTypes.func.isRequired,
};
export const LazilyLoadFactory = (Component, modules) => {
return (props) => (
<LazilyLoad modules={modules}>
{(mods) => <Component {...mods} {...props} />}
</LazilyLoad>
);
};
export const importLazy = (promise) => (
promise.then((result) => result)
);
export default LazilyLoad;
import LazilyLoad, { importLazy, LazilyLoadFactory } from './LazilyLoad'
异步加载组件有两种方式
1)使用高阶组件包裹现有的页面组件,当页面加载时,被引用的组件会同时被异步加载,并且通过props传递给页面组件。
class PageTest extends React.Component {
render() {
const { Breadcrumb, Table, Pagination } = this.props;
return (
<div id="page-test">
<Breadcrumb menuDataList={this.props.menuDataList} />
...
</div>
)
}
}
PageTest = LazilyLoadFactory(PageTest, {
Breadcrumb: () => System.import('../../components/breadcrumb'),
Table: () => System.import('../../components/cTable'),
Pagination: () => System.import('../../components/pagination'),
})
2) 按需加载组件:比如某个组件在首屏时并不显示,只有等弹窗时才需要显示,那么这个组件就可以采用按需加载的方式进行异步加载。
class PageTestEdit extends React.Component {
...
//返回LazilyLoad包裹后的组件
createLazilyModule(moduleFn) {
return (
<LazilyLoad modules={{
Datepicker: () => System.import('../../components/datepicker')
}}>
{moduleFn}
</LazilyLoad>
)
}
renderModuleEdit() {
return (
<div className="padding-20" id="edit-module">
{this.createLazilyModule(({Datepicker}) => {
return <Datepicker type="datetime" placeholder="请选择"/>
})}
</div>
)
}
...
}
Webpack2.x Lazy Loading - React: https://webpack.js.org/guides/lazy-load-react/
基于Webpack 2的React组件懒加载: https://segmentfault.com/a/1190000007938737