如何使用preact进行手动代码拆分?

时间:2019-05-25 06:19:47

标签: javascript code-splitting preact

我想使用preact手动进行代码拆分。 Preact已经为路由拆分了代码,但是我想自己做。

我的用例是,我正在构建一个工具,用户可以在其中将小部件添加到仪表板。在主页上,我只想包含用户已配置的小部件的代码,而不是用户未使用的小部件的代码。

因此,我不想在bundle.js中捆绑所有小部件的代码,但是在呈现小部件列表时需要时懒惰地请求它。

我尝试使用async!语法,我在一些较旧的提交模板中看到了这种语法,但这没用。

我的代码的简化示例

配置数据

[{ "type": "notes", "title": "Widget 1}, { "type": "todo", "title": "Widget 2"}]

列表的渲染功能

const Grid = ({ widgets }) => (
    <ul>
        {widgets.map((widget) => <li key={widget.title}><Widget widget={widget} /></li>)}
    </ul>
);

小部件组件

这里有一个从类型到组件的映射:

import notes from widgets/notes;
import todo from widgets/todo;

class Widget extends Component {
    widgetMap(widget) {
      if (widget.type === 'notes') {
         return notes;
      }
      if (widget.type === 'todo') {
          return todo;
      }
    }

    render ({ widget }) {
        const widgetComponent = this.widgetMap(map);
        return (
            <div>
                <h1>{widget.title}</h1>
                <widgetComponent />
            </div>
        );
    } 
}

1 个答案:

答案 0 :(得分:1)

如果您使用的是Preact X,它具有<Suspense>lazy的特性,这也是React也使用的相同API。您可以在此处详细了解以下内容:https://reactjs.org/docs/concurrent-mode-suspense.html

您修改的示例如下所示(从here调整的代码):

import { Suspense, lazy } from `preact/compat`;

const notes = lazy(() => import('./widgets/notes'));
const todo = lazy(() => import('./widgets/todo'));

class Widget extends Component {
    widgetMap(widget) {
      if (widget.type === 'notes') {
         return notes;
      }
      if (widget.type === 'todo') {
          return todo;
      }
    }

    render ({ widget }) {
        const widgetComponent = this.widgetMap(map);
        return (
            <Suspense fallback={<div>loading...</div>}>
                <div>
                    <h1>{widget.title}</h1>
                    <widgetComponent />
                </div>
            </Suspense>
        );
    } 
}

对于较早版本的Preact,只要您设置了Babel或其他一些编译器来处理dynamic module loading

,就可以自己将异步加载HOC放在一起
export default asyncComponent = (importComponent) => {
  class AsyncComponent extends Component {
    constructor(props) {
      super(props);
      this.state = { component: null };
    }

    async componentDidMount() {
      const { default: component } = await importComponent();
      this.setState({ component });
    }

    render() {
      const Component = this.state.component;
      return Component ? <Component {...this.props} /> : <div>loading...</div>;
    }
  }

  return AsyncComponent;
}