Webpack + Express + EJS: Error: Cannot find module “.”

匿名 (未验证) 提交于 2019-12-03 02:26:02

问题:

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:

package.json:

{   "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"   } } 

webpack.config.js

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"     } }; 

src/index.js

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); 

views/index.ejs

hello world 

Reproduction steps:

  • Run webpack to build the project
  • Start the server with node dist/server.js
  • Visit http://localhost:8000
  • Expect to see the contents of index.ejs, instead get above stack trace

Any idea what's going wrong?

回答1:

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.



回答2:

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



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!