如何使用 preact 进行手动代码拆分?
How can I do manual code-splitting with 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>
);
}
}
如果您使用的是 Preact X,它具有 <Suspense>
和 lazy
相同的功能 API React 也使用。你可以在这里阅读更多关于它的深度: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 或其他一些转译器来处理,你就可以自己组合异步加载 HOC dynamic module loading
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;
}
我想使用 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>
);
}
}
如果您使用的是 Preact X,它具有 <Suspense>
和 lazy
相同的功能 API React 也使用。你可以在这里阅读更多关于它的深度: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 或其他一些转译器来处理,你就可以自己组合异步加载 HOC dynamic module loading
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;
}