Search code examples
javascriptnode.jsecmascript-6es6-modules

Why is this code not awaiting import of modules?


I am trying to dynamically import modules when the nodejs server is in development environment. I have created an immediately-invoked async function for this which theoretically should work, but it simply doesn't. The rest of the code following the import of modules runs without awaiting for the import to finish.

server.js

    import express from 'express'; // standard import
    
    if (process.env.NODE_ENV === 'development') {
    // IIFE to dynamically import modules required in dev
     (
      async () => {
            
         try {
         console.log(`About to import`)
         //simple destructuring used to get the default export out of the modules
         const {default: webpack} = await import('webpack');
         const {default: webpackDevMiddleware} = await import('webpack-dev-middleware');
         console.log(`FIRST: typeof webpack ${typeof Webpack} | typeof webpackdevmiddleware ${typeof WebpackDevMiddleware}`)
          } catch (error) {
             console.log(error)
          }
       })();
     }
    
    const server = express();
    
    if (process.env.NODE_ENV === 'development') {
    // Need to use imported modules here but this code does not wait for the webpack imports above to finish
    console.log(`SECOND: I must run after FIRST`)
    }
    
    ....
    server.listen(PORT, () => {
    console.log(`Server is listening on port 8080`);
});

When I run the server.js code I get the following output in this order:

About to import

SECOND: I must run after FIRST

Server is listening on port 8080

FIRST: typeof webpack function | typeof webpackdevmiddleware function

The correct order needs to be:

About to import

FIRST: typeof webpack function | typeof webpackdevmiddleware function

SECOND: I must run after FIRST

Server is listening on port 8080

I cannot understand where/why it is going wrong?


Solution

  • As the others have already suggested in the comments, this pattern of executing something is called IIFE:

    (async () => { /* ... */ })();
    

    Since it is asnychronous it will not "wait" until finished but execute parallel to the code following.

    If you want something to happen in sequential order, you have to include that part inside the async environment as well or name the file something.mjs so you can use await in the top level.