如何实现 React 模块动态导入
如何实现 React 模块动态导入
React 模块动态导入

代码分割
webpack & code splitting
https://reactjs.org/docs/code-splitting.html
https://zh-hans.reactjs.org/docs/code-splitting.html
Code-Splitting 可以创建多个可在运行时动态加载的包
https://webpack.js.org/guides/code-splitting/
https://rollupjs.org/guide/en/#code-splitting
https://github.com/browserify/factor-bundle
虽然您并未减少应用程序中的全部代码量,但避免了加载用户可能永远不需要的代码,并减少了初始加载过程中所需的代码量。
https://create-react-app.dev/docs/code-splitting/
https://nextjs.org/docs/advanced-features/dynamic-import
React.lazy and Suspense are not yet available for server-side rendering.
code-splitting & server-side rendering
https://github.com/gregberge/loadable-components
https://loadable-components.com/docs/server-side-rendering/
React.lazy
React.lazy 函数让你可以可以像导入将常规组件一样的渲染一个动态导入。
import OtherComponent from './OtherComponent';
// React.lazy
const OtherComponent = React.lazy(() => import('./OtherComponent'));
首次呈现此组件时,它将自动加载包含OtherComponent的捆绑包。
React.lazy 采用了必须调用动态 import()的函数。
这必须返回一个 Promise,该 Promise 解析为一个带有默认导出的模块,该模块包含一个 React组件。
然后,应该将懒惰的组件呈现在Suspense组件中,这使我们可以在等待懒惰的组件加载时显示一些后备内容(例如加载指示符)。
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
fallback prop 支持在等待组件加载时接受要渲染的任何React元素
您可以将 Suspense 组件放置在 lazy 组件上方的任何位置
您甚至可以用一个 Suspense 组件包装多个惰性组件。
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</Suspense>
</div>
);
}
Error boundaries
错误边界
如果另一个模块无法加载(例如,由于网络故障),它将触发错误
您可以处理这些错误,以显示良好的用户体验,并通过错误边界管理恢复
创建错误边界后,您可以在惰性组件上方的任何位置使用它来在出现网络错误时显示错误状态。
import React, { Suspense } from 'react';
import MyErrorBoundary from './MyErrorBoundary';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
const MyComponent = () => (
<div>
<MyErrorBoundary>
<Suspense fallback={<div>Loading...</div>}>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</Suspense>
</MyErrorBoundary>
</div>
);
https://reactjs.org/docs/error-boundaries.html
Route-based code splitting
基于路由的代码拆分
React Router & React.lazy
确定在应用程序中的何处引入代码拆分可能有些棘手
您要确保选择的位置能够平均拆分捆绑包,但不会破坏用户体验
路线是一个不错的起点
网络上的大多数人习惯了页面过渡,需要花费一些时间来加载
您还倾向于一次重新渲染整个页面,因此您的用户不太可能同时与页面上的其他元素进行交互
这是一个示例,说明如何使用带有 React.lazy 的 React Router 等库将基于路由的代码拆分为您的应用。
import React, {
Suspense,
lazy,
} from 'react';
import {
BrowserRouter as Router,
Route,
Switch,
} from 'react-router-dom';
const Home = lazy(() => import('./routes/Home'));
const About = lazy(() => import('./routes/About'));
const App = () => (
<Router>
<Suspense fallback={<div>Loading...</div>}>
<Switch>
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
</Switch>
</Suspense>
</Router>
);
https://reactjs.org/docs/code-splitting.html#route-based-code-splitting
react-router
https://reacttraining.com/react-router/
Named Exports
命名的导出
React.lazy 当前仅支持默认导出
如果要导入的模块使用命名的导出,则可以创建一个中间模块,将其重新导出为默认模块
这样可以确保摇树不停,并且不会拉扯未使用的组件
// ManyComponents.js
export const MyComponent = /* ... */;
export const MyUnusedComponent = /* ... */;
// MyComponent.js
// 中间模块, 导出为默认模块
export { MyComponent as default } from "./ManyComponents.js";
// MyApp.js
import React, { lazy } from 'react';
const MyComponent = lazy(() => import("./MyComponent.js"));
webpack
https://webpack.js.org/guides/code-splitting/
module.exports = {
entry: {
main: './src/app.js',
},
output: {
// `filename` provides a template for naming your bundles (remember to use `[name]`)
filename: '[name].bundle.js',
// `chunkFilename` provides a template for naming code-split bundles (optional)
chunkFilename: '[name].bundle.js',
// `path` is the folder where Webpack will place your bundles
path: './dist',
// `publicPath` is where Webpack will load your bundles from (optional)
publicPath: 'dist/'
}
};
https://gist.github.com/gaearon/ca6e803f5c604d37468b0091d9959269
webpack & magic-comments
https://webpack.js.org/api/module-methods/#magic-comments
https://webpack.docschina.org/api/module-methods/#magic-comments
// Single target
import(
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: "lazy" */
/* webpackExports: ["default", "named"] */
'module'
);
// Multiple possible targets
import(
/* webpackInclude: /\.json$/ */
/* webpackExclude: /\.noimport\.json$/ */
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: "lazy" */
/* webpackPrefetch: true */
/* webpackPreload: true */
`./locale/${language}`
);
import(/* webpackIgnore: true */ 'ignored-module.js');
babel
https://classic.yarnpkg.com/en/package/@babel/plugin-syntax-dynamic-import
$ yarn add -D @babel/plugin-syntax-dynamic-import
https://babeljs.io/docs/en/babel-plugin-syntax-dynamic-import
$ npm i -D @babel/plugin-syntax-dynamic-import
{
"plugins": ["@babel/plugin-syntax-dynamic-import"]
}
// webpack config
const config = {
entry: [
"core-js/modules/es.promise",
"core-js/modules/es.array.iterator",
path.resolve(__dirname, "src/main.js"),
],
// ...
};
// or
// src/main.js
import "core-js/modules/es.promise";
import "core-js/modules/es.array.iterator";
// ...

https://www.npmjs.com/package/babel-plugin-dynamic-import-node
https://github.com/airbnb/babel-plugin-dynamic-import-node
$ yarn add -D babel-plugin-dynamic-import-node
.babelrc
{
"plugins": ["dynamic-import-node"]
}
dynamic import
https://webpack.js.org/guides/code-splitting/#dynamic-imports
import("./emoji-component").then(emoji => {
// 使用 promise
console.log(emoji));
});
切换路由
react-router
lazy-load
延迟加载 / 懒加载
code splitting & dynamic import
import()类似函数的形式将模块名称作为参数,并返回一个Promise,该Promise始终解析为模块的名称空间对象
https://github.com/tc39/proposal-dynamic-import
http://2ality.com/2017/01/import-operator.html#loading-code-on-demand
https://create-react-app.dev/docs/code-splitting/
const moduleA = `ESM (code splitting & dynamic import)`;
export { moduleA };
这将使 moduleA.js 及其所有唯一依赖项成为单独的块,仅在用户单击“加载”按钮后才加载
import React, { Component } from 'react';
class App extends Component {
handleClick = () => {
import('./moduleA')
.then(({ moduleA }) => {
// Use moduleA
})
.catch(err => {
// Handle failure
});
};
render() {
return (
<div>
<button onClick={this.handleClick}>Load</button>
</div>
);
}
}
export default App;
async / await & promise
如果愿意,还可以将其与 async / await 语法一起使用
// async / await
async handleClick = () => {
const moduleA = await import('./moduleA');
moduleA.then(({ moduleA }) => {
// Use moduleA
})
.catch(err => {
// Handle failure
});
};
chunks
https://create-react-app.dev/docs/production-build
refs
xgqfrms 2012-2020
www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
如何实现 React 模块动态导入的更多相关文章
- 反射attr以及模块动态导入
一.实现自省的四个函数 1.hasattr判断一个对象中有没有一个name字符串对应的方法或属性 class BlackMedium: feture="Ugly" def __in ...
- python 反射 动态导入模块 类attr属性
1.反射 hasattr getattr delattr setattr 优点:事先定义好接口,接口只有在被完成后才能真正执行,这实现了即插即用,这其实是一种“后期绑定”,即先定义好接口, 然后是再去 ...
- 封装,封装的原理,Property ,setter ,deleter,多态,内置函数 ,__str__ , __del__,反射,动态导入模块
1,封装 ## 什么是封装 what 对外隐藏内部的属性,以及实现细节,并给外部提供使用的接口 学习封装的目的:就是为了能够限制外界对内部数据的方法 注意 :封装有隐藏的意思,但不是单纯的隐藏 pyt ...
- day26 封装、多态、内置函数、反射、动态导入
今日内容 1.封装 什么是封装? 封装从字面意思上看就只将某种东西封起来装好,当我们代码中的某些方法与属性不想让外界进行访问时,就对这些属性进行特殊的处理,使这种属性或者方法不能被外界直接进行访问或者 ...
- python面向对象反射-框架原理-动态导入-元类-自定义类-单例模式-项目的生命周期-05
反射 reflect 反射(reflect)其实是反省,自省的意思 反省:指的是一个对象应该具备可以检测.修改.增加自身属性的能力 反射:通过字符串获取对象或者类的属性,进行操作 设计框架时需要通过反 ...
- Python之路-python(面向对象进阶(模块的动态导入、断言、Socket Server))
模块的动态导入 断言 Socket Server 一.模块的动态导入 class C(object): def __init__(self): self.name = "zhangsan&q ...
- Python 动态导入模块
动态导入模块 目录结构: zhangsandeMacBook-Air:1110 zhangsan$ tree . . ├── lib │ └── aa.py ├── test1.py lib目录下 ...
- Python 实现接口类的两种方式+邮件提醒+动态导入模块+反射(参考Django中间件源码)
实现接口类的两种方式 方式一 from abc import ABCMeta from abc import abstractmethod class BaseMessage(metaclass=AB ...
- python importlib动态导入模块
一般而言,当我们需要某些功能的模块时(无论是内置模块或自定义功能的模块),可以通过import module 或者 from * import module的方式导入,这属于静态导入,很容易理解. 而 ...
随机推荐
- 全栈性能测试修炼宝典-JMeter实战笔记(二)
性能测试初体验 性能测试实质:利用工具去模拟大量用户操作来验证系统能够承受的负载情况,找出潜在的性能问题,分析并解决:找出系统性能变化趋势,为后续的扩展提供参考 测试分类 测试内容中,负载测试.压力测 ...
- jQuery 真伪数组的转换
//真数组转换伪数组 var arr = [1,3,5,7,9]; var obj = {}; [].push.apply(obj,arr); console.log(obj) //伪数组转真数组 v ...
- python RecursionError: maximum recursion depth exceeded while calling
import copyimport sys # 导入sys模块sys.setrecursionlimit(8192) # 将默认的递归深度修改为r = sys.getrecursionlimit()_ ...
- 类型检查和鸭子类型 Duck typing in computer programming is an application of the duck test 鸭子测试 鸭子类型 指示编译器将类的类型检查安排在运行时而不是编译时 type checking can be specified to occur at run time rather than compile time.
Go所提供的面向对象功能十分简洁,但却兼具了类型检查和鸭子类型两者的有点,这是何等优秀的设计啊! Duck typing in computer programming is an applicati ...
- https://www.hutool.cn/ 糊涂
一个Java基础工具类,对文件.流.加密解密.转码.正则.线程.XML等JDK方法进行封装,组成各种Util工具类,同时提供以下组件: 模块 介绍 hutool-aop JDK动态代理封装,提供非IO ...
- virtualenv安装和配置
安装命令 命令执行结束 配 执行命令:virtualenv testvir 执行完成:会在当前目录下生成如下文件夹 进入到testvir目录 进入Scripts目录: 进入虚拟环境:执行 activa ...
- Webpack4.0各个击破(1)html篇
webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高.本系列是笔者自己的学习记录,比较基础,希望通过问题 + 解决方式的模式,以前端构建中遇到的具体需求为出发点,学习we ...
- SSRF漏洞挖掘利用技巧
参考文章 SSRF漏洞(原理&绕过姿势) SSRF绕过方法总结 SSRF绕过IP限制方法总结 Tag: #SSRF Ref: 概述 总结 利用一个可以发起网络请求的服务当作跳板来攻击内部其他服 ...
- 重绘和回流(Repaint & Reflow)总结,以及如何进行优化
1. 浏览器渲染机制 浏览器采用流式布局模型(Flow Based Layout) 浏览器会把HTML解析成DOM,把CSS解析成CSSOM,DOM和CSSOM合并就产生了渲染树(Render Tre ...
- 七:Spring Security 前后端分离登录,非法请求直接返回 JSON
Spring Security 前后端分离登录,非法请求直接返回 JSON 解决方案 在 Spring Security 中未获认证的请求默认会重定向到登录页,但是在前后端分离的登录中,这个默认行为则 ...