question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cannot use declared variables in import inside dynamic callback

See original GitHub issue

Bug report

Describe the bug

I’m currently using v9.5.0 and when attempting to use a variable defined inside the callback of dynamic it throws an error: ReferenceError: locale is not defined. Although if I move the variable definition to outside the function it works fine.

To Reproduce

Code snippet:

Failed example:

const DynamicComponent = dynamic(
  () => {
    const locale = getUserLocale();
    console.log(locale); // It doesn't even reach here ...
    return import(`~/translations/${locale}.json`)
      .then(handleFileContent)
  },
  { loading: () => <p>Loading...</p>, ssr: false }
)

// error output: "ReferenceError: locale is not defined"

Working example:

const locale = getUserLocale();
const DynamicComponent = dynamic(
  () => {
    console.log(locale); // console.log works as expected
    return import(`~/translations/${locale}.json`)
      .then(handleFileContent)
  },
  { loading: () => <p>Loading...</p>, ssr: false }
)

Expected behavior

Variables declared inside the callback of dynamic should be allowed to use during import call.

System information

  • OS: macOs
  • Version of Next.js: 9.5.0
  • Version of Node.js: 13.14.0

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:12 (1 by maintainers)

github_iconTop GitHub Comments

2reactions
MihirGHcommented, Oct 2, 2020

So, this is my setup, I have forked the with-dynamic-export example locally to replicate the above scenario:


const getComponentName = (index) => `hello${index}`

const DynamicComponent1 = dynamic(() => import('../components/hello1'))

const DynamicComponent2WithCustomLoading = dynamic(
  () => {
    const componentName = getComponentName(2)
    console.log('componentName', componentName)
    return import(`../components/${componentName}`)
  },
  { loading: () => <p>Loading caused by client page transition ...</p> }
)

When I go and look at the index.js inside .next folder, these two components are resolved differently. That’s why I think something is wrong with Webpack when using variables inside import (have added new lines for readability)

eval("__webpack_require__.r(__webpack_exports__);

/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");

* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);

/* harmony import */ var _components_Header__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../components/Header */ \"./components/Header.js\");\n

/* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! next/dynamic */ \"next/dynamic\");

/* harmony import */ var next_dynamic__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(next_dynamic__WEBPACK_IMPORTED_MODULE_2__);\nvar _jsxFileName = \"/Users/mihirshah/FrontEndLearning/next.js/examples/with-dynamic-import/pages/index.js\";

var __jsx = react__WEBPACK_IMPORTED_MODULE_0___default.a.createElement;

const getComponentName = index => `hello${index}`;

const DynamicComponent1 = next_dynamic__WEBPACK_IMPORTED_MODULE_2___default()(() => __webpack_require__.e(/*! import() */ 0).then(__webpack_require__.bind(null, /*! ../components/hello1 */ \"./components/hello1.js\")), {\n  loadableGenerated: {\n    webpack: () => [/*require.resolve*/(/*! ../components/hello1 */ \"./components/hello1.js\")],\n    modules: ['../components/hello1']\n  }\n});

const DynamicComponent2WithCustomLoading = next_dynamic__WEBPACK_IMPORTED_MODULE_2___default()(() => {\n  const componentName = getComponentName(2);\n  console.log('componentName', componentName);\n  return __webpack_require__(\"./components lazy recursive ^\\\\.\\\\/.*$\")(`./${componentName}`);\n}, {\n  loading: () => __jsx(\"p\", {\n    __self: undefined,\n    __source: {\n      fileName: _jsxFileName,\n      lineNumber: 15,\n      columnNumber: 20\n    }\n  }, \"Loading caused by client page transition ...\"),\n  loadableGenerated: {\n    webpack: () => [/*require.resolve*/(__webpack_require__(\"./components weak recursive ^\\\\.\\\\/.*$\").resolve(`./${componentName}`))],\n    modules: [`../components/${componentName}`]\n  }\n});")

In the first case, it is using something called __webpack_require__.e(/*! import() */ 0)

In the second case, it basically generated its own helper function and using that __webpack_require__(\"./components lazy recursive ^\\\\.\\\\/.*$\") and calling it with ./${componentName}

I am not much of an expert with Webpack so I don’t know if this is helpful or not, but this is what I was able to find.

1reaction
thegiantbeastcommented, Oct 2, 2020

@MihirGH while you’re at it can you output the following example:

const component2 = `hello2`

const DynamicComponent2WithCustomLoading = dynamic(
  () => {
    console.log('componentName', component2)
    return import(`../components/${component2}`)
  },
  { loading: () => <p>Loading caused by client page transition ...</p> }
)

Because this example is working for me and maybe we can compare with your previous one and see if we can see any major difference.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Dynamic ES6 module scopes - javascript - Stack Overflow
So by saying dynamic module scope I mean that module variables can be defined/loaded runtime, which will allow to extend ES6 syntax to...
Read more >
ES2020: `import()` – dynamically importing ES modules - 2ality
First, this import declaration can only appear at the top level of a module. That prevents you from importing modules inside an if...
Read more >
Understand Dynamic Importing in JavaScript
To dynamically import a module, we need to use import keyword as a function. When used as a function, this will return a...
Read more >
Advanced Features: Dynamic Import - Next.js
dynamic () can't be used inside of React rendering as it needs to be marked in the top level of the module for...
Read more >
Dynamic imports - The Modern JavaScript Tutorial
First, we can't dynamically generate any parameters of import . ... Or, we could use let module = await import(modulePath) if inside an ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found