Using webpack > 5
version. Below is my appDevMiddleware.js
congifuration
const path = require('path');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
function createWebpackMiddleware(compiler, publicPath) {
return webpackDevMiddleware(compiler, {
// noInfo: true,
publicPath,
// silent: true,
stats: 'errors-only',
});
}
module.exports = function addDevMiddlewares(app, webpackConfig) {
const compiler = webpack(webpackConfig);
const middleware = createWebpackMiddleware(compiler, webpackConfig.output.publicPath);
app.use(middleware);
app.use(webpackHotMiddleware(compiler));
// Since webpackDevMiddleware uses memory-fs internally to store build
// artifacts, we use it instead
const fs = middleware.fileSystem;
app.get('*', (req, res) => {
fs.readFile(path.join(compiler.outputPath, 'index.html'), (err, file) => {
if (err) {
res.sendStatus(404);
} else {
res.send(file.toString());
}
});
});
};
When i do npm start
of my React App, i’m getting
TypeError: Cannot read property 'readFile' of undefined
at D:master-instore-dashboardservermiddlewaresaddDevMiddlewares.js:29:8
This is exactly showing here
fs.readFile(path.join(compiler.outputPath, 'index.html'), (err, file) => {
I will have to somehow use the promises
for readFile which is something like const { readFile } = require('fs').promises
How should i replace const fs = middleware.fileSystem;
with promise for this issue?
Advertisement
Answer
webpack-dev-middleware
uses memfs as its default outputFileSystem. WDM
didn’t expose the API so that you can NOT get the outputFileSystem
from the instance of WDM
. That’s why you got that error.
You should create your own outputfilesystem
, you can use the memfs
to do that explicitly. Then, you can get the index.html
from the memory file system.
You can use util.promisify()
method from util
Node.js built-in module to promisify the fs.readFile
method.
E.g.
webpack.config.js
:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: path.resolve(__dirname, "src/index.js"),
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js",
},
plugins: [new HtmlWebpackPlugin({ template: "./src/index.html" })],
mode: "development",
};
app.js
:
const path = require("path");
const util = require("util");
const express = require("express");
const webpack = require("webpack");
const webpackDevMiddleware = require("webpack-dev-middleware");
const { createFsFromVolume, Volume } = require("memfs");
const webpackConfig = require("./webpack.config");
const compiler = webpack(webpackConfig);
const app = express();
const fs = createFsFromVolume(new Volume());
fs.join = path.join.bind(path);
const readFile = util.promisify(fs.readFile);
const middleware = webpackDevMiddleware(compiler, {
publicPath: webpackConfig.output.publicPath,
stats: "errors-only",
outputFileSystem: fs,
});
app.use(middleware);
app.get("*", async (req, res) => {
try {
const file = await readFile(path.join(compiler.outputPath, "index.html"));
res.send(file.toString());
} catch (error) {
res.sendStatus(404);
}
});
app.listen(3000, () => console.log("Example app listening on port 3000!"));
Start the server:
⚡ node app.js
Example app listening on port 3000!
Access http://localhost:3000/test
:
⚡ curl http://localhost:3000/test <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script defer src="bundle.js"></script></head>
<body>
</body>
</html>
package version:
{
"name": "68618902",
"devDependencies": {
"html-webpack-plugin": "^5.3.2",
"memfs": "^3.2.2",
"webpack": "^5.51.1",
"webpack-dev-middleware": "^5.0.0"
},
"dependencies": {
"express": "^4.17.1"
}
}