0

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.

j0hnm4r5
  • 407
  • 3
  • 17
  • Sounds like maybe you should create a third library that is compiled with your component, then import the compiled library into both your server-side and client-side code. – JDB May 09 '18 at 20:20
  • To use ES6 Modules on node, you need to use the `--experimental-modules` flag and name the files with `.mjs`, see: https://nodejs.org/api/esm.html – Gabriel Carneiro May 09 '18 at 20:40
  • @GabrielCarneiro, sorry, I should have been more clear; I'd rather avoid using experimental features unless they are legitimately the best option. This problem seems like it should be solvable without needing to resort to that. I also don't necessarily want to import an ES6 module into Node; I want to convert and import it as a CommonJS into Node, while also leaving it alone so it can be imported as an ES6 module elsewhere. – j0hnm4r5 May 09 '18 at 20:45

1 Answers1

2

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
j0hnm4r5
  • 407
  • 3
  • 17