Javascript 动态导入:我遗漏了什么吗?

Javascript 动态导入:我遗漏了什么吗?,javascript,reactjs,webpack,dynamic-import,Javascript,Reactjs,Webpack,Dynamic Import,我有一个React项目,它使用Webpack作为捆绑程序,我将我的捆绑包分为两部分——主代码库main.js,和供应商捆绑包vendor.js 在构建这些捆绑包之后,main.js最终为45kb,vendor.js为651kb 一个特定的供应商库是225kb,似乎是供应商导入中最严重的违规者 我正在文件顶部的页面组件中导入此库: 从“React”导入React; 从“heavyPackage”导入{ModuleA,ModuleB};//225kb进口 ... 常量页=({setThing})=>

我有一个React项目,它使用Webpack作为捆绑程序,我将我的捆绑包分为两部分——主代码库
main.js
,和供应商捆绑包
vendor.js

在构建这些捆绑包之后,
main.js
最终为45kb,
vendor.js
为651kb

一个特定的供应商库是225kb,似乎是供应商导入中最严重的违规者

我正在文件顶部的页面组件中导入此库:

从“React”导入React;
从“heavyPackage”导入{ModuleA,ModuleB};//225kb进口
...
常量页=({setThing})=>{
...
};
为了尝试将这个繁重的导入加载到一个单独的包中,我尝试使用动态导入来导入这些模块

页面
组件中,直到调用特定函数,模块才被实际使用,因此我尝试在该范围内而不是在文件顶部导入模块:

从“React”导入React;
...
常量页=({setThing})=>{
...
const handleSignIn=async()=>{
const scopedPackage=wait import('heavyPackage');
常量{moduleA,moduleB}=scopedPackage;
//此处通常使用模块A和模块B
};
};
出于某种原因,我认为Webpack会智能地接受我在这里尝试做的事情,并将这个沉重的包分离成它自己的块,只有在需要时才下载,但最终的包是相同的——一个是45kb的
main.js
,一个是651kb的
vendor.js
。我在这里的思路是否正确,可能是我的网页配置已关闭,还是我对动态导入的想法是错误的

编辑我已将网页包配置为使用
拆分块
拆分捆绑包。以下是我如何配置此功能的:

优化:{
chunkId:“命名”,
分割块:{
缓存组:{
公地:{
块:“首字母”,
maxInitialRequests:5,
minChunks:2,
minSize:0,
},
供应商:{
块:“首字母”,
是的,
名称:“供应商”,
优先事项:10,
测试:/node_模块/,
},
},
},
},

好的,那你看!你有一个带有
splitChunks
属性的网页包配置,你还需要在
webpack
输出
对象旁边添加一个
chunkFilename
属性

以CRA生成的一个为例

      // The build folder.
      path: isEnvProduction ? paths.appBuild : undefined,
      // Add /* filename */ comments to generated require()s in the output.
      pathinfo: isEnvDevelopment,
      // There will be one main bundle, and one file per asynchronous chunk.
      // In development, it does not produce real files.
      filename: isEnvProduction
        ? 'static/js/[name].[contenthash:8].js'
        : isEnvDevelopment && 'static/js/bundle.js',
      // TODO: remove this when upgrading to webpack 5
      futureEmitAssets: true,

      // THIS IS THE ONE I TALK ABOUT
      chunkFilename: isEnvProduction
        ? 'static/js/[name].[contenthash:8].chunk.js'
        : isEnvDevelopment && 'static/js/[name].chunk.js',
      // webpack uses `publicPath` to determine where the app is being served from.
      // It requires a trailing slash, or the file assets will get an incorrect path.
      // We inferred the "public path" (such as / or /my-project) from homepage.
      publicPath: paths.publicUrlOrPath,
      // Point sourcemap entries to original disk location (format as URL on Windows)
      devtoolModuleFilenameTemplate: isEnvProduction
        ? info =>
            path
              .relative(paths.appSrc, info.absoluteResourcePath)
              .replace(/\\/g, '/')
        : isEnvDevelopment &&
          (info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
      // Prevents conflicts when multiple webpack runtimes (from different apps)
      // are used on the same page.
      jsonpFunction: `webpackJsonp${appPackageJson.name}`,
      // this defaults to 'window', but by setting it to 'this' then
      // module chunks which are built will work in web workers as well.
      globalObject: 'this',
    },
一旦你把它放在你的网页上。下一步是安装一个
npmi-D@babel/plugin语法动态导入
,并将其添加到babel.config.js中

module.exports=api=>
...
返回{
预设:[
.....
],
插件:[
....
“@babel/plugin语法动态导入”,
....
]
}
然后最后一件事
npm安装react loadable
创建一个名为:
containers
的文件夹。把所有的容器都放进去

在index.js内部执行以下操作:

可加载对象有两个属性

export const List=可加载({
加载程序:()=>导入(/*WebPackageChunkName:“列表”*/“/list constainer”),
加载:加载,
});
  • 加载器:要动态导入的组件
  • loadinh:加载动态组件之前要显示的组件
最后在你们的路由器上设置每一个可加载的路由

。。。
从“./../containers”导入{Lists,List,User}”;
...
导出函数App():React.ReactElement{
返回(
侧导航
标题
儿子2
);
}
因此,当您捆绑您的代码时,我们会得到如下结果:


那好吧,看!你有一个带有
splitChunks
属性的网页包配置,你还需要在
webpack
输出
对象旁边添加一个
chunkFilename
属性

以CRA生成的一个为例

      // The build folder.
      path: isEnvProduction ? paths.appBuild : undefined,
      // Add /* filename */ comments to generated require()s in the output.
      pathinfo: isEnvDevelopment,
      // There will be one main bundle, and one file per asynchronous chunk.
      // In development, it does not produce real files.
      filename: isEnvProduction
        ? 'static/js/[name].[contenthash:8].js'
        : isEnvDevelopment && 'static/js/bundle.js',
      // TODO: remove this when upgrading to webpack 5
      futureEmitAssets: true,

      // THIS IS THE ONE I TALK ABOUT
      chunkFilename: isEnvProduction
        ? 'static/js/[name].[contenthash:8].chunk.js'
        : isEnvDevelopment && 'static/js/[name].chunk.js',
      // webpack uses `publicPath` to determine where the app is being served from.
      // It requires a trailing slash, or the file assets will get an incorrect path.
      // We inferred the "public path" (such as / or /my-project) from homepage.
      publicPath: paths.publicUrlOrPath,
      // Point sourcemap entries to original disk location (format as URL on Windows)
      devtoolModuleFilenameTemplate: isEnvProduction
        ? info =>
            path
              .relative(paths.appSrc, info.absoluteResourcePath)
              .replace(/\\/g, '/')
        : isEnvDevelopment &&
          (info => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')),
      // Prevents conflicts when multiple webpack runtimes (from different apps)
      // are used on the same page.
      jsonpFunction: `webpackJsonp${appPackageJson.name}`,
      // this defaults to 'window', but by setting it to 'this' then
      // module chunks which are built will work in web workers as well.
      globalObject: 'this',
    },
一旦你把它放在你的网页上。下一步是安装一个
npmi-D@babel/plugin语法动态导入
,并将其添加到babel.config.js中

module.exports=api=>
...
返回{
预设:[
.....
],
插件:[
....
“@babel/plugin语法动态导入”,
....
]
}
然后最后一件事
npm安装react loadable
创建一个名为:
containers
的文件夹。把所有的容器都放进去

在index.js内部执行以下操作:

可加载对象有两个属性

export const List=可加载({
加载程序:()=>导入(/*WebPackageChunkName:“列表”*/“/list constainer”),
加载:加载,
});
  • 加载器:要动态导入的组件
  • loadinh:加载动态组件之前要显示的组件
最后在你们的路由器上设置每一个可加载的路由

。。。
从“./../containers”导入{Lists,List,User}”;
...
导出函数App():React.ReactElement{
返回(
侧导航
标题
儿子2
);
}
因此,当您捆绑您的代码时,我们会得到如下结果:


@Ernesto的答案提供了一种代码拆分的方法,通过使用
react loadable
babel dynamic import
插件howev