【问题标题】:Webpack Lazy Loading with Typescript使用 Typescript 进行 Webpack 延迟加载
【发布时间】:2018-08-30 18:58:40
【问题描述】:

我遇到了延迟加载和 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”文件到底有什么区别?

【问题讨论】:

    标签: typescript webpack webpack-4


    【解决方案1】:

    无法将 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();
    

    *note-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;
        };
    }
    

    【讨论】:

      【解决方案2】:

      我有一个技巧可以延迟加载具有其类型的模块:

      function lazyLoad(){ return let lazyModule:typeof import('xxx') = require('xxx'); }

      限制:xxx只能是字符串,不能是变量

      【讨论】:

        【解决方案3】:

        Dynamic imports are an ES feature,您需要告诉 TypeScript 转换为 ESNext 以在输出中获取 import,只需将 "module": "commonjs" 更改为 "module": "esnext"

        获取此代码:

        export const LoadMe = () => import('./a-module')
        
        • "module": "commonjs" 编译为 module.exports.LoadMe = () =&gt; require('a-module'),Webpack 无法知道它是动态的还是普通的 require
        • "module": "esnext" 编译为 export const LoadMe = () =&gt; import('a-module'),Webpack 知道它是动态的,因为它是对 import 的调用表达式

        【讨论】:

        • 谢谢。这有帮助 ;) 现在我只需要让我的代码与 esnext 一起工作 ;)
        • 如果您使用"module": "esnext",如何将插件导入您的 webpack.config.ts 文件?每当我尝试将模块导入/需要模块到我的 webpack 文件中时,我都会遇到一堆语法错误。
        • 我的 Webpack 配置不使用 TypeScript,但如果你这样做了,你可以使用 const module = require('somewhere') 而不是 import module from 'somewhere'。您可能需要@types/node 才能让require 工作。
        猜你喜欢
        • 2017-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-15
        • 2021-11-12
        • 2016-04-27
        • 1970-01-01
        相关资源
        最近更新 更多