I'm creating a node/express server that I'm trying to bundle so that I can deploy it onto an IIS server. I should note that this is a backend server only. Once I try to run the code after it has been bundled, I get the following error:
ReferenceError: __WEBPACK_EXTERNAL_MODULE_dotenv__ is not defined
at eval (webpack:///external_%22dotenv%22?:1:18)
at Object.dotenv (C:\inetpub\wwwroot\my-deployments\server\bundle.js:271:1)
at __webpack_require__ (C:\inetpub\wwwroot\my-deployments\server\bundle.js:20:30)
at eval (webpack:///./src/server/server.js?:4:1)
at Object../src/server/server.js (C:\inetpub\wwwroot\my-deployments\server\bundle.js:169:1)
at __webpack_require__ (C:\inetpub\wwwroot\my-deployments\server\bundle.js:20:30)
at eval (webpack:///multi_./src/server/server.js?:1:18)
at Object.0 (C:\inetpub\wwwroot\my-deployments\server\bundle.js:216:1)
at __webpack_require__ (C:\inetpub\wwwroot\my-deployments\server\bundle.js:20:30)
at C:\inetpub\wwwroot\my-deployments\server\bundle.js:84:18
I understand that there seems to be an error with the dotenv module, however I tried with a basic app that only had express installed, and I got the same error but with express instead of dotenv. I figure this is an issue with my webpack.config.js but I can't seem to figure out what would be causing this problem.
webpack.config.js
const path = require('path')
const webpack = require('webpack')
const nodeExternals = require('webpack-node-externals')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
target: 'node',
mode: 'development',
entry: {
bundle: ["./src/server/server.js"]
},
externals: [nodeExternals({
importType: 'umd'
})],
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'server'
})
],
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
}
}
The issue is in your nodeExternals options. Remove importType: 'umd' and re-bundle. I tested this locally with a small express app and your exact config and it worked for me.
The issue here is that you're telling webpack that all your imports are "external" (not bundled) and that they use umd (Universal Module Definition) to expose their contents.
Umd is often used for client side code so it'll run in multiple different environments (<script> tags, commonjs, amd, es6 modules and so on). As for server side / Nodejs only modules... not so much. The default value of importType is commonjs, which is Node's native module loading system and what the vast majority of server side packages will be using.
Related
I want to load my package.json in an ES6 environment and access it like pkg.name.
My solution so far is making a simple module for reading the file with fs, parsing it and import this module in every place I need to access it.
The problem is, I want to bundle my script with webpack and the path to the package.json is resolved to my current path from my pc I bundle everything. Like: D:/dev/app-name/package.json
This is wrong, I need a way to run the bundled script afterwards on e.g. a separate pc, or linux and still find the package.json. Is there a way to tell webpack to not resolve this path, or is there another (simpler) way to use the "root" path in my script?
My bundled app is an express server and I'm using webpack 5.
src/api/package-json.js:
import path from 'path'
import { fileURLToPath } from 'url'
import fs from 'fs-extra'
// Path CONST
// we need to change up how __dirname is used for ES6 purposes
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const PROJECT_ROOT = path.join(__dirname, '..', '..')
const PKG_FILE = path.join(PROJECT_ROOT, 'package.json')
// Package.json
const pkg = JSON.parse(fs.readFileSync(PKG_FILE)) // import pkg from '~root/package.json'
export default pkg
src/api/app.js:
import pkg from './package-json.js'
console.log(pkg.name)
webpack.config.js:
import path from 'path'
import { fileURLToPath } from 'url'
// import nodeExternals from 'webpack-node-externals'
// we need to change up how __dirname is used for ES6 purposes
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const { NODE_ENV = 'production' } = process.env
export default {
entry: './src/api/app.js',
mode: NODE_ENV,
target: 'node',
node: {
global: false,
__filename: false,
__dirname: false
},
output: {
path: path.resolve(__dirname, 'dist', 'server'),
filename: 'app.cjs'
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx']
},
externals: {
'node-pty': 'commonjs2 node-pty'
}
}
I found a workaround with process.cwd(), but I don't think this is a good solution for my problem. The problem is, process.cwd() can be changed in runtime as far as I know. :(
src/api/package-json.js:
import path from 'path'
import fs from 'fs-extra'
// Path CONST
const PROJECT_ROOT = process.cwd()
const PKG_FILE = path.join(PROJECT_ROOT, 'package.json')
// Package.json
const pkg = JSON.parse(fs.readFileSync(PKG_FILE)) // import pkg from '~root/package.json'
export default pkg
I have created nodejs console app and trying to minify it with webpack.
webpack.config.js I got:
const path = require('path');
module.exports = {
externals: {
fs: "require('fs')",
readline: "require('readline')",
},
entry: './index.js',
output: {
path: path.resolve(__dirname, 'bin'),
filename: 'bin.js'
},
mode: 'development'
};
Everything goes ok before I run builded app:
readline.js:189
input.on('data', ondata);
^
TypeError: input.on is not a function
at new Interface (readline.js:189:11)
at Object.createInterface (readline.js:69:10)
What should I do to prevent this error?
Somewhere I found the solution. In the webpack configuration file I must set target: node to point the collector what to do with standard external packages (e.g. readline, fs, path, etc.).
I'm trying to update my app node backend to typescript and I keep hitting this syntax error:
/Users/Shared/website/src/server.ts:1
(function (exports, require, module, __filename, __dirname) { import *
as express from 'express';
^
SyntaxError: Unexpected token *
I have my tsconfig/webpack/server, etc set up as follows:
server.ts
import * as express from 'express';
import * as path from 'path';
const app = express();
const port = process.env.PORT || 3000;
app.use(express.static(path.join(__dirname, 'dist')));
app.get('*', function(req, res, next){
res.sendFile(path.resolve(__dirname, '/public', 'index.html'));
});
app.listen(port, () => console.log(`Listening on port ${port}!`));
webpack.config.json:
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const outputDirectory = 'dist';
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "bundle.js",
path: path.join(__dirname, outputDirectory)
},
mode: 'development',
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".ts", ".tsx", ".js", ".json"]
},
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "ts-loader" },
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" },
{
test: /\.scss$/,
use: [
"style-loader", // creates style nodes from JS strings
"css-loader", // translates CSS into CommonJS
"sass-loader" // compiles Sass to CSS, using Node Sass by default
]
}
]
},
// When importing a module whose path matches one of the following, just
// assume a corresponding global variable exists and use that instead.
// This is important because it allows us to avoid bundling all of our
// dependencies, which allows browsers to cache those libraries between builds.
externals: {
},
plugins: [
new CleanWebpackPlugin([outputDirectory]),
new HtmlWebpackPlugin({
template: './public/index.html',
favicon: './public/favicon.gif'
}),
new CopyWebpackPlugin([
{ from: 'public' }
])
]
};
tsconfig.json:
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": false,
"module": "commonjs",
"target": "es6",
"jsx": "react"
},
"include": [
"./src/**/*"
],
}
The build process succeeds, but I hit the syntaxError on run. I have a react front end also set up using typescript / tsx and it works just fine. I seem to just be running into issues with the server.ts / node files. I'm very new to trying to get this all set up, but I wanted practice making a site with numerous technologies (react/node/typescript/sass/webpack/etc). So far I have everything except the typescript/node relationship.
I had the same problem, after I realised that the tsconfig wasn't applied.
If
"module": "commonjs"
was in effect, you wouldn't have this error.
I faced the same problem before. I solve it by changing the import 'call':
From:
import * as express from 'express';
To:
const express = require('express');
As others have stated, the problem is that your tsconfig.json is not applied to server.ts. You have left out important details of your setup which is why others cannot duplicate this problem.
I have a good guess at what the issue is and having struggled with this identical problem myself, I will explain my guess here in the hope of helping some other poor soul being tormented by this issue.
The basic problem is that your server code is in a different tree than your react code. This is why the tsconfig.json is not being applied to it since (I believe) it is outside the "./src/" path specified. (Perhaps "./website/src/").
You haven't shown us the package.json file but very likely the server entry is something like "server": "ts-node ./website/src/server.ts"
To verify that the tsconfig.json application is the issue try this from the command line...
$ ts-node -O '{\"module\":\"commonjs\"}' ./website/src/server.ts
Chances are, things will start working. Now the solution is probably as simple as adding another path your tsconfig.json includes.
So I came across this post on github where basically there are two sort of working methods presented since you’re using a bundling tool targeted to es6 add
"allowSyntheticDefaultImports": true to ”compilerOptions”
Or change
import express from "express";
to
import express = require('express');
This might be happening if your tsconfig.json isn't at the root of your project. Configure webpack to point to your target config file (which you can alter with variables to point to dev and prod configurations).
https://github.com/TypeStrong/ts-loader
If set, will parse the TypeScript configuration file with given absolute path as base path. Per default the directory of the configuration file is used as base path. Relative paths in the configuration file are resolved with respect to the base path when parsed. Option context allows to set option configFile to a path other than the project root (e.g. a NPM package), while the base path for ts-loader can remain the project root.
Try modifying your webpack.config.js file to have this:
module.exports = {
...
module: {
rules: [
{
options: {
configFile: path.join(__dirname, "tsconfig.json")
}
}
]
}
};
• I recently implemented server side rendering using Angular Universal in my application.
• This required converting my node server file from .js to .ts.
• Typescript is compiled to javascript using webpack
• Everything works when I run the server using : ts-node server.ts
• After compiling to javascript using webpack, I get the following error for Firebase API's used in my server:
ERROR in ./node_modules/google-auto-auth/node_modules/mime/index.js
Module not found: Error: Can't resolve './types/standard' in '/Users/XX/Desktop/XX/XX/node_modules/google-auto-auth/node_modules/mime'
ERROR in ./node_modules/#google-cloud/storage/node_modules/mime/index.js
Module not found: Error: Can't resolve './types/standard' in '/Users/XX/Desktop/XX/OM-XX/node_modules/#google-cloud/storage/node_modules/mime'
etc. etc.
How can this be tackled?
My webpack config code:
const path = require('path');
const webpack = require('webpack');
module.exports = {
entry: {server: './server.ts'},
resolve: {extensions: ['.js', '.ts']},
target: 'node',
mode: 'none',
// this makes sure we include node_modules and other 3rd party libraries
externals: [/(node_modules|main\..*\.js)/],
output: {
path: __dirname,
filename: '[name].js'
},
module: {
rules: [
{test: /\.ts$/, loader: 'ts-loader'}
]
},
plugins: [
// Temporary Fix for issue: https://github.com/angular/angular/issues/11580
// for "WARNING Critical dependency: the request of a dependency is an expression"
new webpack.ContextReplacementPlugin(
/(.+)?angular(\\|\/)core(.+)?/,
path.join(__dirname, 'src'), // location of your src
{} // a map of your routes
),
new webpack.ContextReplacementPlugin(
/(.+)?express(\\|\/)(.+)?/,
path.join(__dirname, 'src'),
{}
)
]
}
Thank you!
Maybe this can be related to missing types?
Try to install missing typesfor all the packages that throw error
e.g: npm install --save #types/google-cloud__storage
I am trying to set up my first project using Webpack and Express but somehow I am doing something wrong.
This is what I did:
1. CREATED SAMPLE PROJECT
Created a sample project using express-generator. My folder structure is something like:
express-project
-app.js
-webpack.config.js
-public
-javascripts
-modules
-build
2. SET UP HANDLEBARS
Set up handlebars as view/template engine and created a couple of routes
3. WEBPACK CODE
Created the Webpack specific code/configuration as follows
webpack.config.js
var webpack = require('webpack');
var path = require('path');
var webpackHotMiddleware = 'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=2000&overlay=false';
module.exports = {
resolve: {
alias: {
handlebars: path.resolve('public/vendor/handlebars-v4.0.5.js'),
bootstrap: path.resolve('public/vendor/bootstrap/js/bootstrap.js'),
pubsub: path.resolve('public/vendor/ba-tiny-pubsub.js')
}
},
context: path.resolve('public/javascripts'),
entry: {
cart: ['./modules/cart', webpackHotMiddleware],
index: ['./modules/products.js', webpackHotMiddleware],
vendor: ['bootstrap', 'pubsub', webpackHotMiddleware]
},
output: {
path: path.resolve('public/javascripts/build'),
publicPath: 'javascripts/build/',
filename: '[name].js',
chunkFilename: "[id].js"
},
module: {
loaders: [
// some loaders here
]
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
}
app.js
// some code before
var app = express();
(function() {
// Step 1: Create & configure a webpack compiler
var webpack = require('webpack');
var webpackConfig = require(process.env.WEBPACK_CONFIG ? process.env.WEBPACK_CONFIG : './webpack.config');
var compiler = webpack(webpackConfig);
// Step 2: Attach the dev middleware to the compiler & the server
app.use(require("webpack-dev-middleware")(compiler, {
noInfo: false,
publicPath: webpackConfig.output.publicPath,
stats: {
colors: true
}
}));
// Step 3: Attach the hot middleware to the compiler & the server
app.use(require("webpack-hot-middleware")(compiler, {
log: console.log,
path: '/__webpack_hmr',
heartbeat: 10 * 1000
}));
})();
// some code after
4. JS CODE ON TEMPLATE
Then on the handlebars page I require the bundled javascripts
<script src="javascripts/build/common.js"></script>
<script src="javascripts/build/vendor.js"></script>
<script src="javascripts/build/cart.js"></script>
5. NPM START
Finally if I start the server using the standard npm start I see in the shell that webpack bundles everything with no errors but if I go to localhost:3000/ it does not find any of the assets created by Webpack. Instead if I run webpack to create the various bundles as if I were on production, everything is created correctly and it works as expected.
Hope someone can figure out what I am doing wrong.
Thanks
I managed to figure out what was causing the problem, by adding a slash in these 2 lines everything started to work properly:
context: path.resolve('public/javascripts/'),
path: path.resolve('public/javascripts/build/'),