Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Named import umd module returns null when the module uses the export let syntax #14353

Open
7 tasks done
anyesu opened this issue Sep 11, 2023 · 3 comments
Open
7 tasks done
Labels
feat: deps optimizer Esbuild Dependencies Optimization p3-minor-bug An edge case that only affects very specific usage (priority)

Comments

@anyesu
Copy link
Contributor

anyesu commented Sep 11, 2023

Describe the bug

I used the vue-amap library in my project. I found that when I imported it using import { lazyAMapApiLoaderInstance } from 'vue-amap' , the value of lazyAMapApiLoaderInstance was always null instead of the latest value.

The source code of lazyAMapApiLoaderInstance uses the export let syntax to delay initialization:

let lazyAMapApiLoaderInstance = null;
import AMapAPILoader from './lazy-amap-api-loader';
import Vue from 'vue';
export const initAMapApiLoader = (config) => {
  if (Vue.prototype.$isServer) return;
  // if (lazyAMapApiLoaderInstance) throw new Error('You has already initial your lazyAMapApiLoaderInstance, just import it');
  if (lazyAMapApiLoaderInstance) return;
  if (!lazyAMapApiLoaderInstance) lazyAMapApiLoaderInstance = new AMapAPILoader(config);
  lazyAMapApiLoaderInstance.load();
};
export { lazyAMapApiLoaderInstance };

ref: https://stackoverflow.com/a/32558929

Reproduction

https://stackblitz.com/edit/vitejs-vite-tdtcgx?file=src%2Fmain.js

Steps to reproduce

pnpm i
# run with Vite
pnpm run dev
# run with Vue CLI
pnpm run dev:vue-cli

Use Vite and Vue CLI to start the project respectively. You can see from the log that the result in Vite is null , while the result in Vue CLI is the expected object .

vite-bug

Then build and run in production mode :

pnpm run build && pnpm run preview

pnpm run build:vue-cli && pnpm run preview

vite-bug

You can see that the behavior in production mode is the same as running in Vue CLI .

The source code after Vite transform is as follows:

import __vite__cjsImport0_vueAmap from "/node_modules/.vite/deps/vue-amap.js?v=7da0ea0b"; const initAMapApiLoader = __vite__cjsImport0_vueAmap["initAMapApiLoader"]; const lazyAMapApiLoaderInstance = __vite__cjsImport0_vueAmap["lazyAMapApiLoaderInstance"];
initAMapApiLoader();
console.log(
  process.env.VITE_APP ? 'vite' : 'vue-cli',
  lazyAMapApiLoaderInstance
);

However, the source code after Webpack transform is as follows:

__webpack_require__.r(__webpack_exports__);
/* harmony import */ var vue_amap__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue-amap */ "./node_modules/.pnpm/vue-amap@0.5.10/node_modules/vue-amap/dist/index.js");
/* harmony import */ var vue_amap__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(vue_amap__WEBPACK_IMPORTED_MODULE_0__);

Object(vue_amap__WEBPACK_IMPORTED_MODULE_0__["initAMapApiLoader"])();
console.log(
  Object({"NODE_ENV":"development","BASE_URL":"/"}).VITE_APP ? 'vite' : 'vue-cli',
  vue_amap__WEBPACK_IMPORTED_MODULE_0__["lazyAMapApiLoaderInstance"]
);

The difference is that Webpack will convert lazyAMapApiLoaderInstance to vue_amap__WEBPACK_IMPORTED_MODULE_0__["lazyAMapApiLoaderInstance"] , while Vite simply defines a local variable to take the value, so console.log cannot read the latest value.

So I think the behavior of Vite should be consistent with Webpack, at least the development mode and production mode should be consistent in Vite.

There are two ways to solve this problem:

  • Rename variable bindings like Webpack .

    If simply use RegExp to replace them, it may affect other comments, strings, and local variables with the same name.

    If AST is introduced for parsing, things may become much more complicated. I'm not familiar with AST either.

  • This should be documented, in this case the namespace import should be used instead of the named import as shown below. Also throwing warning in transformCjsImport .

    lines.push(`const ${localName} = ${cjsModuleName}["${importedName}"]`)

    import * as VueAMap from 'vue-amap';
    VueAMap.initAMapApiLoader();
    console.log(
      process.env.VITE_APP ? 'vite' : 'vue-cli',
      VueAMap.lazyAMapApiLoaderInstance
    );

System Info

System:
    OS: Windows 10 10.0.19045
    CPU: (16) x64 11th Gen Intel(R) Core(TM) i7-11700 @ 2.50GHz
    Memory: 26.00 GB / 47.81 GB
  Binaries:
    Node: 16.20.2 - ~\AppData\Local\pnpm\node.EXE
    Yarn: 1.22.18 - D:\software\nodejs\node_global\yarn.CMD
    npm: 8.19.4 - ~\AppData\Local\pnpm\npm.CMD
    pnpm: 8.6.12 - ~\AppData\Local\pnpm\pnpm.EXE
  Browsers:
    Edge: Spartan (44.19041.1266.0), Chromium (116.0.1938.69)
    Internet Explorer: 11.0.19041.1566

Used Package Manager

pnpm

Logs

No response

Validations

@stackblitz
Copy link

stackblitz bot commented Sep 11, 2023

Fix this issue in StackBlitz Codeflow Start a new pull request in StackBlitz Codeflow.

@bluwy bluwy added p3-minor-bug An edge case that only affects very specific usage (priority) feat: deps optimizer Esbuild Dependencies Optimization and removed pending triage labels Sep 17, 2023
@bluwy
Copy link
Member

bluwy commented Sep 17, 2023

This is hard to fix. We're only rewriting to const initAMapApiLoader = __vite__cjsImport0_vueAmap["initAMapApiLoader"] because vue-amap does not export ESM, so we have to access the APIs through the default import after prebundling. Rewriting it for each referenced variables in code instead would be expensive, but not impossible since we're already doing it for SSR.

@anyesu
Copy link
Contributor Author

anyesu commented Sep 18, 2023

Waiting for you to have a better solution to fix this. I'm currently using this workaround since this case is used less in my projects.

import * as VueAMap from 'vue-amap';
VueAMap.initAMapApiLoader();
console.log(VueAMap.lazyAMapApiLoaderInstance);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feat: deps optimizer Esbuild Dependencies Optimization p3-minor-bug An edge case that only affects very specific usage (priority)
Projects
None yet
Development

No branches or pull requests

2 participants