Webpack Lazy Loading with Typescript

北城以北 提交于 2020-07-09 11:56:06

问题


I have a problem with lazy loading and webpack.

There is a video of Sean Larkin showing how easy it is with webpack 4 to create a lazy loaded bundle (Here). But when I try to do it with typescript I run into some problems.

index.ts

export const someThing = something => import("./lazy/lazy");

and

lazy/lazy.ts
export default "I am lazy";

when I run it without any webpack configuration and name the files to ".js" I get a main chunk and a small chunk for the lazy loaded module.

But when I run it as ".ts" files with a simple webpack configuration I get just the "main.js" file and no extra chunk.

webpack.config.js
let config = {
    resolve: {
        extensions: [".ts", ".js"]
    },
    module: {
        rules: [
            { test: /\.ts$/, use: ["ts-loader"], exclude: /node_modules/ },
        ]
    },
}

module.exports = config;

and

tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es5",
        "noImplicitAny": false,
        "sourceMap": true,
        "lib": [ "es6", "dom" ],
        "removeComments": true
    }
}

Is there something to configure I am mission? What exactly is the difference between the import of a "js" file to a "ts" file?


回答1:


Dynamic imports are an ES feature, you need to tell TypeScript to transform to ESNext to get import on the output, just change "module": "commonjs" to "module": "esnext".

Take this code :

export const LoadMe = () => import('./a-module')
  • "module": "commonjs" compiles to module.exports.LoadMe = () => require('a-module'), Webpack can't know if it's dynamic or just a normal require
  • "module": "esnext" compiles to export const LoadMe = () => import('a-module'), Webpack knows it's dynamic because it's a call expression to import



回答2:


I have a trick one to lazyLoad a module with its type:

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

limitation: the xxx can only be string not a variable.




回答3:


There is no way to configure the Typescript compiler to not touch certain imports. The old way of lazy loading works just as well though:

require.ensure([], require => {
  const lodash = require('lodash') as typeof import('lodash');
}, 'lodash-chunk');

this can be wrapped in a promise to achieve a very similar behavior to the 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 is not generic - this function will need to be duplicated for every module you want to lazy load.

You'll also need to declare the require.ensure interface based on your enabled libs. I use this in my custom typings file

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


来源:https://stackoverflow.com/questions/49410022/webpack-lazy-loading-with-typescript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!