Express JS with Webpack giving cannot find module error - node.js

Hi I am new with frontend technologies so I have a question around webpack and express js. I am building an application using react , webpack , node and express js. The app.js looks like the following
app.js
const express = require('express');
const app = express();
var path = require('path');
app.use(express.static(__dirname + '/'));
app.get('/', (req, res) => { // new
res.sendFile(__dirname + "/index.html");
});
app.listen(3000, () => console.log('listening on port 3000'));
package.json looks like following
"version": "1.0.0",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 0",
"build": "webpack --mode production",
"start": "nohup webpack-dev-server --mode development --open &",
"prepublishOnly": "cp -r configuration/* build/"
},
"repository": {
"type": "git",
"url": "ssh://git.amazon.com/pkg/SPSWebApplication"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#babel/core": "^7.3.4",
"#babel/preset-env": "^7.3.4",
"#babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.5",
"express": "^4.16.4",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"react-dom": "^16.8.4",
"webpack": "^4.29.6",
"webpack-cli": "^3.3.0",
"webpack-dev-middleware": "^3.6.1",
"webpack-dev-server": "^3.2.1"
},
"dependencies": {
"#stencil-react/core": "*",
"#stencil-react/theme-default": "*",
"webpack": "^4.29.6",
"webpack-cli": "^3.3.0",
"react": "^16.8.4",
"webpack-dev-server": "^3.2.1",
"html-webpack-plugin": "^3.2.0"
},
"description": ""
}
webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
}
]
},
resolve: { // this allows to import 'Foo.jsx'
extensions: ['.jsx', '.js', '.json']
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
})
]
};
when i build the code in the build folder it creates dist/app.js,main.js,index.html whenever i try to run app.js it says
Error: Cannot find module 'express'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:649:15)
at Function.Module._load (internal/modules/cjs/loader.js:575:25)
at Module.require (internal/modules/cjs/loader.js:705:19)
at require (internal/modules/cjs/helpers.js:14:16)
I want to run my application in production environment through dist/app.js but when I do "node app.js" it gives me this dependency issue I am assuming webpack should pull the express dependency in dist/* folder in a minified form which i am assuming it is not doing. Can you please if I am missing anything and my understanding is correct or not?

Related

How to configure webpack to deploy react application on heroku?

I have created a react application from scratch and I'm trying to deploy it on heroku but unfortunately I faced a lot of errors, however I came to the point where I need to add a start script to my package.json file according to the logs of heroku :
npm ERR! Missing script: "start"
I don't know what content to add to my start script command in the package.json because I don't know if it takes additional webpack configuration or not, here is the file :
{
"name": "APPNAME",
"version": "1.0.0",
"description": " web application, etc..",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --mode development",
"build" : "webpack --mode production"
},
"repository": {
"type": "git",
"url": "gitrepo"
},
"author": "LOUKACH EL-Mehdi",
"license": "ISC",
"bugs": {
"url": "ISSUES"
},
"homepage": "readme",
"devDependencies": {
"#babel/cli": "^7.1.0",
"#babel/core": "^7.1.0",
"#babel/preset-env": "^7.1.0",
"#babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.2",
"css-loader": "^5.2.7",
"style-loader": "^2.0.0",
"webpack": "^4.46.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.3"
},
"dependencies": {
"aos": "^2.3.4",
"bootstrap": "^5.1.3",
"express": "^4.18.1",
"react": "^18.2.0",
"react-bootstrap": "^2.4.0",
"react-dom": "^18.2.0",
"react-flow-renderer": "^10.3.11"
}
}
I have a webpack.config.js file that allows me to parse the bundle.js file :
const path = require("path");
const webpack = require("webpack");
module.exports = {
entry: "./src/index.js",
mode: "development",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader",
options: { presets: ["#babel/env"] }
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
},
resolve: { extensions: ["*", ".js", ".jsx"] },
output: {
path: path.resolve(__dirname, "dist/"),
publicPath: "/dist/",
filename: "bundle.js"
},
devServer: {
static : {
directory : path.join(__dirname, "public/")
},
port: 3000,
devMiddleware:{
publicPath: "https://localhost:3000/dist/",
},
hot: "only",
},
plugins: [new webpack.HotModuleReplacementPlugin()]
};
P.S : after browsing the internet, I found out about an express file can be added to the root directory of the project, please let me know if this is the way to go to deploy the application on heroku, thank you !

Why is contextBridge not being imported in my Electron app?

I'm writing an Electron app with React and Typescript, using Webpack, Babel and ESLint but I'm having trouble setting:
mainWindow = new BrowserWindow({
title: "Biomech",
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
enableRemoteModule: false,
sandbox: true,
preload: path.join(__dirname, "./preload.js"),
nativeWindowOpen: true,
},
});
which I want as a security measure.
The reason being that, if I set the webPreferences as specified above, I need to use contextBridge and a preload script that binds the functions that are using IPC to the window. And the problem is that contextBridge is not being properly imported in my preload.ts:
import { contextBridge, ipcRenderer } from "electron";
import { readFileSync } from 'fs';
import { History } from 'history';
import { LIST_DRIVE_FILES_CHANNEL, LOAD_PREV_TEST_RESULTS_CHANNEL, OAUTH2_ACCESS_TOKEN_REQUEST_CHANNEL } from "../src/constants/ipcChannels";
import { VISUALIZE_RESULTS_PATH } from "../src/constants/urls";
// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
"api", {
exchangeCodeForAccessToken: (code: string) => {
ipcRenderer.invoke(OAUTH2_ACCESS_TOKEN_REQUEST_CHANNEL, code);
},
listDriveFiles: (accessToken: string) => {
ipcRenderer.invoke(LIST_DRIVE_FILES_CHANNEL, accessToken);
},
openDirectoryDialog: (history: History) => {
ipcRenderer.invoke(LOAD_PREV_TEST_RESULTS_CHANNEL).then((dialog: any) => {
if (dialog.canceled) { // canceled with one l is correct
return;
} else {
const selectedDirectory = dialog.filePaths[0];
console.log(readFileSync(selectedDirectory + "/README.md", 'utf-8'));
history.push(VISUALIZE_RESULTS_PATH);
}
})
}
}
);
The way I see it it's properly used like the examples I've seen here in SO, or in the Electron docs. But when I run my main process script: npm run dev:electron which is specified in my package.json:
{
"name": "electron-react-ts-app",
"version": "1.0.0",
"description": "Electron + React + Typescript",
"main": "./dist/main.js",
"preload": "./dist/preload.js",
"scripts": {
"dev": "concurrently --success first \"npm run dev:electron\" \"npm run dev:react\" -k",
"dev:electron": "NODE_ENV=development webpack --config webpack.electron.config.js --mode development && electron .",
"dev:react": "NODE_ENV=development webpack serve --config webpack.react.config.js --mode development",
"build:electron": "NODE_ENV=production webpack --config webpack.electron.config.js --mode production",
"build:react": "NODE_ENV=production webpack --config webpack.react.config.js --mode production",
"build": "npm run build:electron && npm run build:react",
"pack": "electron-builder --dir",
"dist": "electron-builder",
"lint": "eslint .",
"format": "prettier --write \"**/*.+(js|jsx|json|yml|yaml|css|md|vue)\""
},
"keywords": [],
"license": "MIT",
"build": {
"files": [
"dist/",
"node_modules/",
"package.json"
],
"productName": "Example",
"appId": "com.example.app",
"directories": {
"output": "dist"
}
},
"devDependencies": {
"#babel/preset-env": "^7.9.5",
"#babel/preset-react": "^7.9.4",
"#babel/preset-typescript": "^7.9.0",
"#types/electron-devtools-installer": "^2.2.0",
"#types/react-router-dom": "^5.1.7",
"#types/regenerator-runtime": "^0.13.0",
"dpdm": "^3.6.0",
"electron": "^11.2.1",
"electron-builder": "^22.7.0",
"electron-devtools-installer": "^3.1.1",
"eslint": "^7.18.0",
"file-loader": "^6.2.0",
"html-webpack-plugin": "^4.5.1",
"husky": "^4.3.8",
"lint-staged": "^10.5.3",
"prettier": "^2.2.1",
"react-router-dom": "^5.2.0",
"webpack": "^5.11.1",
"webpack-cli": "^4.3.1",
"webpack-dev-server": "^3.11.1"
},
"dependencies": {
"#babel/core": "^7.12.10",
"#popperjs/core": "^2.6.0",
"#types/node": "^14.14.22",
"#types/react": "^17.0.0",
"#types/react-dom": "^17.0.0",
"axios": "^0.21.1",
"babel-loader": "^8.2.2",
"bootstrap": "^4.5.3",
"chokidar": "^3.5.1",
"core-js": "^3.8.3",
"css-loader": "^5.0.1",
"electron-fetch": "^1.7.3",
"fsevents": "^2.3.1",
"ini": "^2.0.0",
"jquery": "^3.5.1",
"react": "^17.0.1",
"react-bootstrap": "^1.4.0",
"react-dom": "^17.0.1",
"react-google-login": "^5.2.2",
"style-loader": "^2.0.0"
},
"husky": {
"hooks": {
"pre-commit": "npm run lint && npm run format"
}
},
"lint-staged": {
"*.+(js|jsx)": "eslint --fix",
"*.+(json|css|md)": "prettier --write"
}
}
I get the following error: Cannot read property 'exposeInMainWorld' of undefined
webpack 5.19.0 compiled successfully in 1793 ms
App threw an error during load
TypeError: Cannot read property 'exposeInMainWorld' of undefined
at Object../electron/preload.ts (/Users/lucas_sg/Documents/ITBA/PF/pf-biomech/dist/preload.js:24:53)
at __webpack_require__ (/Users/lucas_sg/Documents/ITBA/PF/pf-biomech/dist/preload.js:128:41)
at /Users/lucas_sg/Documents/ITBA/PF/pf-biomech/dist/preload.js:252:11
at Object.<anonymous> (/Users/lucas_sg/Documents/ITBA/PF/pf-biomech/dist/preload.js:254:12)
at Module._compile (internal/modules/cjs/loader.js:1152:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1173:10)
at Module.load (internal/modules/cjs/loader.js:992:32)
at Module._load (internal/modules/cjs/loader.js:885:14)
at Function.f._load (electron/js2c/asar_bundle.js:5:12738)
at Module.require (internal/modules/cjs/loader.js:1032:19)
I've checked out this repo regarding Electron security and it doesn't look like he's doing things too different, at least at first glance, but I'm clearly messing something up.
Here's my webpack config (webpack.electron.config.js) in case it's useful:
const path = require("path");
module.exports = [
{
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
devtool: "source-map",
entry: {
main: {
import: "./electron/main.ts",
dependOn: "preload"
},
preload: "./electron/preload.ts"
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].js",
},
target: "electron-main",
module: {
rules: [
{
test: /\.(js|ts|tsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
},
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"],
},
],
},
node: {
__dirname: false,
},
},
];
I think the issue resides in you webpack.config file:
entry: {
main: {
import: "./electron/main.ts",
dependOn: "preload"
},
preload: "./electron/preload.ts"
},
Might be that webpack tries to resolve all "preload.ts" dependency at compile time, plus tries to bundle it together with main.ts file. And in such case it will never get access to contextBridge. The preload.js file should only be run in a separate "context" - "Isolated World" as they refer in the docs.
What I would try is:
remove the dependOn: and preload: lines from you webpack config.
convert preload.ts file to JS (ie. to CommonJS format) - try doing that with TS CLI for now
Your preload.js file should look more or less like this:
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld(
'electron',
{
doThing: () => ipcRenderer.send('do-a-thing')
}
)
copy preload.js to a __dirname (in my case it was /dist)
run electron again
That was the only way I could access "contextBridge" object.

Babel is not transpiling nodejs modules

I've created a few nodejs modules and trying to bundle them using webpack, after been transpiled using babel. But it seems babel is not transpiling modules.
Following is my project structure:
> config
> connection
> controllers
> models
> node_modules
> routes
.babelrc
.env
.gitignore
chalk.console.js
package-lock.json
package.json
Procfile
index-bundle.js
index.js
webpack.config.js
Following is the package.json
{
"name": "index-service",
"version": "0.1.0",
"main": "index.js",
"scripts": {
"dev-run": "webpack && node index-bundle.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"license": "ISC",
"dependencies": {
"#babel/core": "7.11.6",
"#babel/node": "7.10.5",
"#babel/preset-env": "7.11.5",
"babel-loader": "8.1.0",
"body-parser": "1.19.0",
"core-js": "3.6.5",
"dotenv": "8.2.0",
"express": "4.17.1",
"pg": "8.4.0",
"pg-hstore": "2.3.3",
"regenerator-runtime": "0.13.7",
"sequelize": "6.3.5",
"webpack": "4.44.2",
"webpack-node-externals": "2.5.2",
},
"devDependencies": {
"chalk": "^4.1.0",
"nodemon": "^2.0.4",
"webpack-cli": "^3.3.12"
}
}
Following is the index.js
require('core-js/stable');
require('dotenv').config();
require('regenerator-runtime/runtime');
const chalk = require('./chalk.console');
const bodyParser = require('body-parser');
const express = require('express');
....
app.listen(PORT, () => {
console.log(chalk.info(`Service running on port ${PORT}`));
});
Following is the webpack.config.js
const nodeExternals = require('webpack-node-externals');
module.exports = {
mode: "development",
target: 'node',
externals: [nodeExternals()],
entry: './index.js',
output: {
path: __dirname,
filename: 'index-bundle.js'
},
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env']
}
}
}
]
}
};
Following is the .babelrc file:
{
"presets": [
"#babel/preset-env"
]
}
Following is the chalk.console.js:
const chalk = require('chalk');
const error = chalk.redBright;
const success = chalk.greenBright;
const warning = chalk.hex('#ff3d00');
const info = chalk.yellowBright;
//This is where the error is occuring
export {
error,
success,
warning,
info
};
So, whenever I run npm run dev-run
I get the following error
D:\NodeJS Services\Index\chalk.console.js:8
export {
^^^^^^
SyntaxError: Unexpected token 'export'
The exact same project structure and same .babelrc, webpack.config.js, and package.json dependencies are working in my another project, but not this one. I wonder where did I go wrong

node js webpack Undefined envioronment variable

HHHi,
I'm trying to use the .env file to store the API id and key for the API I'm using and it's not working. My .env file is in the root of my working directory as well as the root of the repository where the .gitignore file is. It looks like this:
API_ID=XXXXXX
API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXX
I installed dotenv and in my index.js file in my server directory I call it like this:
const dotenv = require('dotenv');
dotenv.config();
then in my apiCall.js function I try to call the variables from the .env file like this:
const AYLIENTextAPI = require('aylien_textapi');
let textapi = new AYLIENTextAPI({
application_id: process.env.API_ID,
application_key: process.env.API_KEY
});
but the ID and Key are showing up as undefined. What am I doing wrong? I would really appreciate any help.
Thanks,
Mike
UPDATE:
this is my webpack.dev.js file:
const path = require('path')
const webpack = require('webpack')
const HtmlWebPackPlugin = require("html-webpack-plugin")
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
entry: './src/client/index.js',
output : {
libraryTarget: 'var',
library: 'Client'
},
mode: 'development',
devtool: 'source-map',
stats: 'verbose',
module: {
rules: [
{
test: '/\.js$/',
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.scss$/,
use: [ 'style-loader', 'css-loader', 'sass-loader' ]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/client/views/index.html",
filename: "./index.html",
}),
new CleanWebpackPlugin({
// Simulate the removal of files
dry: true,
// Write Logs to Console
verbose: true,
// Automatically remove all unused webpack assets on rebuild
cleanStaleWebpackAssets: true,
protectWebpackAssets: false
})
]
}
this is my package.json file:
{
"name": "example-project",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node src/server/index.js",
"build-prod": "webpack --config webpack.prod.js",
"build-dev": "webpack --config webpack.dev.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"aylien_textapi": "^0.7.0",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"webpack": "^4.41.6",
"webpack-cli": "^3.3.11"
},
"devDependencies": {
"#babel/core": "^7.8.4",
"#babel/preset-env": "^7.8.4",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.2",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.13.1",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"sass-loader": "^8.0.2",
"style-loader": "^1.1.3",
"terser-webpack-plugin": "^2.3.5",
"webpack-dev-server": "^3.10.3",
"workbox-webpack-plugin": "^5.0.0"
}
}
figured it out. I can only access the environment variables on the server side.

How to build (Webpack) the Node Js project using PUG Engine?

I am stuck to build the node js project using webpack and I am using pug engine for front end.
My Project Structure:
bin
controller
- csv.controller.js
public
- stylesheets
- javascript
- images
routes
- csv.route.js
- index.route.js
views
- layouts
-- layout.pug
-index.pug
app.js
Package.json File
{
"name": "csv",
"version": "0.0.0",
"private": true,
"scripts": {
"build": "webpack --mode=production",
"build:dev": "webpack --mode=development",
"start":"nodemon ./app.js",
"start:dev": "webpack-dev-server --mode=development"
},
"dependencies": {
"body-parser": "^1.19.0",
"compression": "^1.7.4",
"cookie-parser": "~1.4.4",
"csv-parser": "^2.3.1",
"csv-writer": "^1.5.0",
"debug": "~2.6.9",
"express": "^4.17.1",
"express-fileupload": "^1.1.6-alpha.5",
"fast-csv": "^3.4.0",
"http-errors": "~1.6.3",
"morgan": "^1.9.1",
"multer": "^1.4.2",
"npm-check-updates": "^3.1.23",
"request": "^2.88.0"
},
"devDependencies": {
"#babel/core": "^7.6.2",
"#babel/preset-env": "^7.6.2",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.2.0",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^4.2.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.8.0",
"pug": "^2.0.4",
"pug-loader": "^2.4.0",
"style-loader": "^1.0.0",
"webpack": "^4.40.2",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.8.1",
"webpack-merge": "^4.2.2"
}
}
Actually what I want, after build, A dist folder contain a build.js or whatever its name and all public folder assets in the same directory. I tried with some below codes to build the project.
Webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const config = {
entry: {
app: "./app.js"
},
target: "node",
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].bundle.js"
},
devServer: {
port: 3000
},
plugins: [
new HtmlWebpackPlugin({
template: "./views/index.pug"
})
],
module: {
rules: [
{
test: /\.pug$/,
use: ["pug-loader"]
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ["file-loader"]
},
{
test: [/.js$/],
exclude: /(node_modules)/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"]
}
}
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
}
};
module.exports = (env, argv) => {
if (argv.mode === "development") {
}
if (argv.mode === "production") {
}
return config;
};
I know this question is old, but just in case somebody is looking for an answer.
You need another Webpack config for app.js, which is express entry point.
Call it webpack.server.js or webpack.server.config.js or whatever convenient. Make sure to include webpack-node-externals:
https://www.npmjs.com/package/webpack-node-externals
It may look something like this:
//webpack.server.js
const path = require('path');
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
module.exports = {
return ({
entry: {
app: ./src/server/app.js,
},
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
filename: '[name].js',
},
target: 'node',
node: {
__dirname: false,
__filename: false,
},
externals: [nodeExternals()],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
],
},
});
};
Also use webpack-dev-middleware in your app.js.
See the below link:
https://webpack.js.org/guides/development/
In package.json include a script that looks something like this:
"server:dev": "webpack --config webpack.config.js && webpack --mode development --config webpack.server.js && node ./dist/app.js",
In your webpack.config.js make the entry point the js file that imports your front-end assets..
That is your stylesheets and any other js codes..
Not sure what css framework you are using.
But, I am using tailwindcss and I have a js entry point file that imports tailwindcss and my other js codes.
So essentially you may need two webpack config files one for the front-end and one for the express server.
Hope I am making sense.

Resources