javascriptnode.jswebpackbabeljswebpack-dev-middleware

Using an ES6 module in both an app and in Node, while using Webpack-Dev-Middleware and Express


Background

Let's say you have an ES2015/ES6 component with a single function as a default export:

component.js

export default function() {
    console.log("Hello, World!");
}

An app to include it in:

app.js

import myComponent from "./component"

myComponent();

And an Node.js/Express server using webpack-dev-middleware, to run Webpack (with Babel) on and serve app.js, and to also include component.js in:

server.js

const express = require("express");
const app = express();

// start the server
app.listen(process.env.EXPRESS_PORT, () => {
    console.log(`App listening on port ${process.env.EXPRESS_PORT}!`);
});

const webpack = require("webpack");
const webpackConfig = require("./webpack.config");
const compiler = webpack(webpackConfig);

// use webpack-dev-middleware to serve the publicPath
app.use(
    require("webpack-dev-middleware")(compiler, {
        logLevel: "warn",
        publicPath: webpackConfig.output.publicPath,
    })
);

// use webpack-hot-middleware for HMR
app.use(require("webpack-hot-middleware")(compiler));

const myComponent = require("./component") // import the component
myComponent(); // use the component

Question

How might you go about using component.js in both server.js, as well as in the webpacked app.js?

Problem

As-is, that component works fine in app.js, but throws a SyntaxError: Unexpected token export in the Node console when trying to do const component = require("./component").

Since Babel is only running via Webpack, and server.js is accessing component.js via the original component and not the bundled/transpiled one, we get the error.

I suppose a solution would be to run Babel twice: once on the component before the server.js is started, and once again in Webpack, but that seems very inelegant and inefficient.


Solution

  • I seem to have stumbled across a working solution: write the module in CommonJS format, and Webpack/Babel will compile it for ES6.

    Working files:

    component.js

    function myComponent() {
        console.log("Hello, World!");
    }
    
    module.exports = { myComponent };
    

    app.js

    import myComponent from "./component"
    
    myComponent();
    

    server.js

    const { myComponent } = require("./component") // import the component
    
    myComponent(); // use the component