Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
402 views
in Technique[技术] by (71.8m points)

ecmascript 6 - Dynamic imports in ES6 with runtime variables

Recently stumbled upon the dynamic import proposal and also this Youtube video . Thought would be a great idea to use it for on demand imports of components in React.

Running into an issue where I was not able to "resolve" a path when import is passed string literals as runtime variables.

for eg:

<div>
  <button onClick={this._fetchComp.bind(this, "../component/Counter")}>Get Async Comp</button>
</div>

Tried with multiple options for _fetchComp, but passing parameters doesnt seem to work . A breakdown of the different options tried.

  1. Template Strings Does Not Work : Getting an the below error on click

Error: Cannot find module '../components/Counter'. at webpackAsyncContext (^.*$:53)

Code

    _fetchComp(res) {
    import(`${res}`).then(() => {
        console.log("Loaded")
    },(err)=>{
        console.log("Error",err)
    })}
  1. Variabes Doesn't work: Getting an error during webpack build as 55:12-23

Critical dependency: the request of a dependency is an expression

**Code**

    _fetchComp(res) {
    import(res).then(() => {
        console.log("Loaded")
    },(err)=>{
        console.log("Error",err)
    })}
  1. String literal Works : Just passing pure string literals . On click i am able to see the chunk being downloaded in the dev tools Network tab

    Code

    _fetchComp(res) {
    import("../components/Counter").then(() => {
        console.log("Loaded")
    },(err)=>{
        console.log("Error",err)
    })}
    

As per the spec,

import() accepts arbitrary strings (with runtime-determined template strings shown here), not just static string literals.

So I was hoping the string literal will do the part, but that doesn't seem to be the case.

I came across a similar issue on flow issue tracker. But the proposed solution advocated use of string literals again.

I'll leave you all with a CodeSandbox link.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The rules for import() for the spec are not the same rules for Webpack itself to be able to process import(). For Webpack to handle an import, it needs to be able to at least guess roughly what an import() is meant to be referencing.

This is why your example of import("../components/Counter") works, because Webpack can be 100% confident in what needs to be loaded.

For your usecase, you could for instance do

_fetchComp(res) {
  import(`../components/${res}`).then(() => {
    console.log("Loaded")
  }, (err)=>{
    console.log("Error", err)
  })
}

with

this._fetchComp.bind(this, "Counter")

and now that Webpack knows that the path starts with ../components/, it can bundle up every component automatically and then load the one you need. The downside here is that because it doesn't know which component you're loading, it has to load them all and there's no guarantee they are all actually being used. That is the tradeoff of dynamic imports.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...