I have a Vue3 project(setted up using vue-cli and run as npm run serve
) which need a const
to be defined so that all services can use it. so my main.js
has this constant
// main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.min.css'
import "jquery"
import "bootstrap-icons/font/bootstrap-icons.css";
let x = 'google'
export {x};
const app = createApp(App)
app.use(store)
app.use(router)
app.mount("#app")
my services/GetCategoriesService.js
is:
import { x } from "../main.js"
console.log(x)
and in my components/footer.vue
<script>
tag i execute the service script:
import * as $ from 'jquery'
import "../services/GetCategoriesService"
This will result in undefined but adding an extra console.log in my service will make hot reloading(I'm NOT refreshing the page)to run and now i can see two console.log with google
then I refresh the page and again see two console.log but with undefined
adding another console.log without refreshing result in three google prints, refresh Then I see three undefined
which is really weird. I'm using Firefox v 105.0
.
NOTE: Using named export of x
and console.log x
inside a function(which is called from footer.vue
) result in same behavior.
CodePudding user response:
You are doing a kind of circular import. To understand what is going on, first, we need to know how the import
work.
The import
process is divided into 3 steps:
- Construction: find, download, and parse all of the files into module records.
- Instantiation: find boxes in memory to place all of the exported values in (but don’t fill them in with values yet). Then make both exports and imports point to those boxes in memory. This is called linking.
- Evaluation: run the code to fill in the boxes with the variables’ actual values.
The normal case:
// main.js
import { x } from './x'
console.log(x)
// x.js
let x = 1
export {x}
The console.log(x)
above will print out 1
because the scenario will appear like below:
- Construction: download and parse
main.js
-> download and parsex.js
- Instantiation: find memory for
x
but don't fill in the value yet - Evaluation: run the code in
x.js
first (because it does not depend on any module) => set the value forx
=> run the code inmain.js
=> show the expected value in theconsole.log
because the valuex
has already been set
The circular import case:
// main.js
import { x } from './x'
console.log(x)
let a = 2
export {a}
// x.js
import {a} from './main'
console.log(a)
let x = 1
export {x}
The console.log(x)
in main.js
will print out 1
but the console.log(a)
in x.js
will print out undefined
because the x.js
will still be run first. Because the JS engine will go down to the bottom of the dependencies graph and execute the module that is at the bottom (usually the module that does not depend on another)
Why does refreshing the page show undefined
in the console.log
?
Because it follows our scenario above
Why does hot-reload show the expected value in console.log
?
Because the hot-reload process just replaces the module that changed. In your case, it is GetCategoriesService.js
. So the main.js
module is unchanged and its variable is already set the values
This answer is based on the knowledge in this awesome article. Highly recommend reading it for the complete picture