This is going to be a little long and I was thinking I should maybe split it into two questions but I feel it all ties together and gives better context, so here goes...My build attempts have been failing for almost two days now and I can't seem to find any solutions. My project is basically a REST API with the index page accessible via localhost:5000. The project structure is as follows:
controllers
init
- db.js
models
public
- css
routes
views
- layout.pug
- index.pug
.babelrc
.env
app.js
start.js
package.json
webpack.server.config.js
webpack.prod.config.js
The entry point of the project is start.js which imports a function from the db.js file and a constant app from the app.js file. The app.js file imports and sets up express const app = express() adds all relevant middleware and exports the constant app. The db.js file in the init folder exports a function, (export default function { ... }), which initializes the database.
app.js and db.js come together inside start.js which looks like so...
import InitializeDB from "./init/db";
import app from "./app";
InitializeDB();
app.set("port", process.env.PORT || 3000);
const server = app.listen(app.get("port"), () => {
console.log(`Express running → PORT ${server.address().port}`);
});
And because I wanted to use ES6 imports, I installed babel npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/node and added this to .babelrc
{
"presets": [
"@babel/preset-env"
]
}
My package.json scripts:
"scripts": {
"build": "rm -rf dist && webpack --mode production --config webpack.server.config.js && webpack --mode production --config webpack.prod.config.js",
"start": "node ./dist/server.bundle.js",
"watch": "nodemon --exec babel-node start.js --ignore public/",
"start:dev": "concurrently \"npm run test\" \"npm run watch\"",
"test": "echo \"Testing...\""
},
Locally, npm run start:dev gets everything running fine. However, that's where my success ends.
My first problem is that when I try to run node ./start.js I get hit with the error (node:149228) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
So then I add "type": "module" in my package.json and run npm run start:dev again but then I get the Error...
internal/modules/run_main.js:54
internalBinding('errors').triggerUncaughtException(
^
Error [ERR_MODULE_NOT_FOUND]: Cannot find module 'G:\apps\myproject\init\db' imported from G:\apps\myproject\start.js
Did you mean to import ../init/db.js?
That's my first problem. Now for the webpack part...
My webpack.server.config.js...
const path = require("path");
const webpack = require("webpack");
const nodeExternals = require("webpack-node-externals");
module.exports = {
entry: {
server: "./start.js",
},
output: {
path: path.join(__dirname, "dist"),
publicPath: "/",
filename: "[name].bundle.js",
},
target: "node",
node: {
__dirname: false,
__filename: false,
},
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
],
},
};
My webpack.prod.config.js file...
const path = require("path");
const webpack = require("webpack");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
entry: {
app: "./start.js",
},
output: {
path: path.join(__dirname, "dist"),
publicPath: "/",
filename: "[name].bundle.js",
},
target: "node",
devtool: "source-map",
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: true,
}),
new OptimizeCSSAssetsPlugin({}),
],
},
module: {
rules: [
{
test: /\.pug$/,
use: ["pug-loader"],
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ["file-loader"],
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader",
},
],
},
plugins: [
new HtmlWebPackPlugin({
template: "./views/index.pug",
}),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css",
}),
],
};
For the webpack.prod.config.js file, some suggest changing target to web instead of node but that hasn't worked for me.
When I run npm run build with "type": "module" set in package.json, webpack throws the error
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: G:\apps\myproject\webpack.server.config.js
require() of ES modules is not supported.
require() of G:\apps\myproject\webpack.server.config.js from G:\apps\myproject\node_modules\webpack-cli\bin\utils\convert-argv.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename webpack.server.config.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from G:\apps\myproject\package.json.
So then I remove "type": "module" from package.json and run npm run build again and this time I get a bunch of...
Critical dependency: the request of a dependency is an expressionand
Module not found: Error: Can't resolve 'net' in 'G:\apps\myproject\node_modules\...
for multiple packages.
These issues have been gnawing at me quite a bit. Your help would be greatly appreciated.
That's my first problem. Now for the webpack part...
Your first problem needs to update your codebase as ESM requires:
*.js files should be renamed to *.mjs. Adding {type: 'module'} in your package.json avoid this tedious operation since it will enable/override this checknode --experimental-modules start.jsrequire, exports, module.exports, __filename, __dirname so you need to change your __dirname to:import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
...
app.use(express.static(path.join(__dirname, 'public')))
...
import Routes from './routes/index.js' // added .js
// etc.. for all the files
At the end, node --experimental-modules start.js will start:

For the webpack part, instead, you need to:
npm i @open-wc/webpack-import-meta-loader -D
And add it to your webpack.prod.config.js file (I just remove UglifyJsPlugin since it wasn't working):
{
test: /\.js$/,
loader: require.resolve('@open-wc/webpack-import-meta-loader')
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With