使用 Typescript 的 Webpack 延迟加载
Webpack Lazy Loading with Typescript
延迟加载和 webpack 有问题
有一个 Sean Larkin 的视频展示了使用 webpack 4 创建延迟加载包是多么容易 (Here)。但是当我尝试用打字稿来做时,我 运行 遇到了一些问题。
index.ts
export const someThing = something => import("./lazy/lazy");
和
lazy/lazy.ts
export default "I am lazy";
当我 运行 它没有任何 webpack 配置并将文件命名为“.js”时,我得到了一个主块和一个用于延迟加载模块的小块。
但是当我 运行 它作为具有简单 webpack 配置的“.ts”文件时,我只得到 "main.js" 文件而没有额外的块。
webpack.config.js
let config = {
resolve: {
extensions: [".ts", ".js"]
},
module: {
rules: [
{ test: /\.ts$/, use: ["ts-loader"], exclude: /node_modules/ },
]
},
}
module.exports = config;
和
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": true,
"lib": [ "es6", "dom" ],
"removeComments": true
}
}
我是任务有什么可以配置的吗?
将 "js" 文件导入到 "ts" 文件到底有什么区别?
Dynamic imports are an ES feature,你需要告诉 TypeScript 转换为 ESNext 以获得输出上的 import
,只需将 "module": "commonjs"
更改为 "module": "esnext"
.
接受这个代码:
export const LoadMe = () => import('./a-module')
"module": "commonjs"
编译为 module.exports.LoadMe = () => require('a-module')
,Webpack 无法知道它是动态的还是普通的 require
"module": "esnext"
编译为 export const LoadMe = () => import('a-module')
,Webpack 知道它是动态的,因为它是对 import
的调用表达式
我有一个技巧,可以延迟加载类型为以下的模块:
function lazyLoad(){
return let lazyModule:typeof import('xxx') = require('xxx');
}
限制:xxx 只能是字符串,不能是变量。
无法将 Typescript 编译器配置为不接触某些导入。
old way 延迟加载也同样有效:
require.ensure([], require => {
const lodash = require('lodash') as typeof import('lodash');
}, 'lodash-chunk');
这可以包装在一个承诺中,以实现与 ES6 非常相似的行为 import
function importLodash(): Promise<typeof import('lodash')> {
return new Promise((resolve, reject) => {
require.ensure([], require => {
resolve(require('lodash'))
}, reject, 'lodash-chunk');
})
}
// then use it
const lodash = await importLodash();
*注意 - require.ensure
不是通用的 - 这个函数需要为每个你想延迟加载的模块复制。
您还需要根据启用的库声明 require.ensure
接口。我在我的自定义类型文件中使用它
/* typings.d.ts */
declare global {
const require: {
// declare webpack's lazy loading interface
ensure(deps: string[], cb: (lazyRequire: (path: string) => any) => void, chunkName: string): void;
ensure(deps: string[], cb: (lazyRequire: (path: string) => any) => void, errCb: (err: Error) => void, chunkName: string): void;
};
}
延迟加载和 webpack 有问题
有一个 Sean Larkin 的视频展示了使用 webpack 4 创建延迟加载包是多么容易 (Here)。但是当我尝试用打字稿来做时,我 运行 遇到了一些问题。
index.ts
export const someThing = something => import("./lazy/lazy");
和
lazy/lazy.ts
export default "I am lazy";
当我 运行 它没有任何 webpack 配置并将文件命名为“.js”时,我得到了一个主块和一个用于延迟加载模块的小块。
但是当我 运行 它作为具有简单 webpack 配置的“.ts”文件时,我只得到 "main.js" 文件而没有额外的块。
webpack.config.js
let config = {
resolve: {
extensions: [".ts", ".js"]
},
module: {
rules: [
{ test: /\.ts$/, use: ["ts-loader"], exclude: /node_modules/ },
]
},
}
module.exports = config;
和
tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": true,
"lib": [ "es6", "dom" ],
"removeComments": true
}
}
我是任务有什么可以配置的吗? 将 "js" 文件导入到 "ts" 文件到底有什么区别?
Dynamic imports are an ES feature,你需要告诉 TypeScript 转换为 ESNext 以获得输出上的 import
,只需将 "module": "commonjs"
更改为 "module": "esnext"
.
接受这个代码:
export const LoadMe = () => import('./a-module')
"module": "commonjs"
编译为module.exports.LoadMe = () => require('a-module')
,Webpack 无法知道它是动态的还是普通的require
"module": "esnext"
编译为export const LoadMe = () => import('a-module')
,Webpack 知道它是动态的,因为它是对import
的调用表达式
我有一个技巧,可以延迟加载类型为以下的模块:
function lazyLoad(){
return let lazyModule:typeof import('xxx') = require('xxx');
}
限制:xxx 只能是字符串,不能是变量。
无法将 Typescript 编译器配置为不接触某些导入。 old way 延迟加载也同样有效:
require.ensure([], require => {
const lodash = require('lodash') as typeof import('lodash');
}, 'lodash-chunk');
这可以包装在一个承诺中,以实现与 ES6 非常相似的行为 import
function importLodash(): Promise<typeof import('lodash')> {
return new Promise((resolve, reject) => {
require.ensure([], require => {
resolve(require('lodash'))
}, reject, 'lodash-chunk');
})
}
// then use it
const lodash = await importLodash();
*注意 - require.ensure
不是通用的 - 这个函数需要为每个你想延迟加载的模块复制。
您还需要根据启用的库声明 require.ensure
接口。我在我的自定义类型文件中使用它
/* typings.d.ts */
declare global {
const require: {
// declare webpack's lazy loading interface
ensure(deps: string[], cb: (lazyRequire: (path: string) => any) => void, chunkName: string): void;
ensure(deps: string[], cb: (lazyRequire: (path: string) => any) => void, errCb: (err: Error) => void, chunkName: string): void;
};
}