I'm writing an express web app with webpack, typescript and ejs. When hitting one of the routes that's supposed to serve a .ejs file I get the following error:
Error: Cannot find module "."
at webpackMissingModule (/Users/max/Development/test/express-webpack/dist/server.js:20669:74)
at new View (/Users/max/Development/test/express-webpack/dist/server.js:20669:152)
at EventEmitter.render (/Users/max/Development/test/express-webpack/dist/server.js:18776:12)
at ServerResponse.render (/Users/max/Development/test/express-webpack/dist/server.js:20479:7)
at /Users/max/Development/test/express-webpack/dist/server.js:25508:7
at Layer.handle [as handle_request] (/Users/max/Development/test/express-webpack/dist/server.js:4524:5)
at next (/Users/max/Development/test/express-webpack/dist/server.js:4743:13)
at Route.dispatch (/Users/max/Development/test/express-webpack/dist/server.js:4724:3)
at Layer.handle [as handle_request] (/Users/max/Development/test/express-webpack/dist/server.js:4524:5)
at /Users/max/Development/test/express-webpack/dist/server.js:4054:22
Here's the code:
{
"name": "express-webpack",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"awesome-typescript-loader": "^3.0.0-beta.18",
"copy-webpack-plugin": "^4.0.1",
"debug": "^2.6.0",
"ejs": "^2.5.5",
"express": "^4.14.0",
"json-loader": "^0.5.4",
"source-map-loader": "^0.1.6",
"webpack": "^2.2.0-rc.3"
}
}
var CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: __dirname + "/src/index.js",
target: "node",
output: {
filename: "server.js",
path: __dirname + "/dist"
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },
{ test: /\.json$/, loader: 'json-loader' },
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
]
},
plugins: [
new CopyWebpackPlugin([
{ from: 'src/views', to: 'views' }
])
],
node: {
fs: "empty"
}
};
var express = require('express');
var app = express();
app.set("view engine", "ejs");
app.set("views", "./views");
app.get('/', function(req, res, next){
res.render('index'); // <-- error originates here AFAIK
});
app.listen(8000);
hello world
webpack
to build the projectnode dist/server.js
http://localhost:8000
Any idea what's going wrong?
Go to the latest release, download ./ejs.js or ./ejs.min.js . Alternately, you can compile it yourself by cloning the repository and running jake build (or $(npm bin)/jake build if jake is not installed globally).
See npm ls | grep ejs at root level of your project to check if you have already added ejs dependency to your project. If not, add it as dependencies to your project. (I prefer adding dependency to package. json instead of npm install ing the module.)
To solve the error "Cannot find module 'html-webpack-plugin'", make sure to install the html-webpack-plugin package by opening your terminal in your project's root directory and running the following command: npm i -D html-webpack-plugin and restart your IDE and dev server.
I digged into webpack generated code and I found it seems there is a bug with context parse evaluation of webpack. There is a simple expression that express uses to require selected view engine, but it is failing to resolve that.
To overcome this issue, in your index you can write
const ejs = require("ejs").__express;
const app = express();
app.set("view engine", "ejs");
app.engine('ejs', ejs);// <-- this does the trick
But if you want a definitive solution, open an issue on webpack repo.
Adding on Cleiton's answer, you now have to have a callback function in while calling app.engine(string, callback)
app.set('views', 'src/views');
app.set('view engine', 'ejs');
app.engine('ejs', require('ejs').__express); //<-- this
I belive your issue it has to do with the fact that your bundled file (dist/server.js) does not have access to your dependencies, express, template engine etc. In order to sort that out you can configure webpack to avoid bundling the dependencies (due to the fact your app is running from server/node side):
var CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
entry: __dirname + "/src/index.js",
target: "node",
output: {
filename: "server.js",
path: __dirname + "/dist"a
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },
{ test: /\.json$/, loader: 'json-loader' },
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
]
},
plugins: [
new CopyWebpackPlugin([
{ from: 'src/views', to: 'views' }
])
],
node: {
fs: "empty"
}
};
// Node module dependencies should not be bundled
config.externals = fs.readdirSync("node_modules")
.reduce(function(acc, mod) {
if (mod === ".bin") {
return acc
}
acc[mod] = "commonjs " + mod
return acc
}
You might also need to override node global config, using the node option config to make the views folder accessible from your bundled file, more details: https://webpack.js.org/configuration/node/#components/sidebar/sidebar.jsx
That config could also help you https://gist.github.com/madx/53853c3d7b527744917f
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