Webpack on browser complains about require not defined - javascript

Here is my folder structure:
src/
└───public/
├───index.js
├───controllers/
├───css/
├───js/
├───models/
├───vendor/
└───views/
└───partials/
I know it's not the best folder structure, but it's one of my earlier projects, and I wanted to test webpack on it.
Anyways the controllers, js, vendor all contain javascript code.
My webpack.dev.config is on the same level as src:
const path = require("path");
const common = require("./webpack.common");
const {merge} = require("webpack-merge");
module.exports = merge(common, {
target: 'node',
mode: "development",
output: {
filename: "[name].bundle.js",
path: path.resolve(__dirname, "dist")
},
plugins: [
],
module: {
}
});
As you can see it merges from webpack.common.js:
const nodeExternals = require('webpack-node-externals');
module.exports = {
externals: [nodeExternals()],
entry: {
main: './src/index.js'
},
module: {
rules: [
{
test: /\.js$/,
}
]
}
}
For now I am hardcoding the location of the bundled js file in my HTML docs, but on the browser when I run this, I see the message Uncaught ReferenceError: require is not defined and I am not sure how to fix it.
Here is index.js:
const express = require('express');
const path = require('path');
const app = express();
const port = process.env.PORT || 8080;
const exphbs = require('express-handlebars');
const Datastore = require('nedb');
const db = new Datastore({
filename: path.join(__dirname, 'public/db/pfam.db'),
autoload: true
});
module.exports.db = db;
app.use(express.static(__dirname + "/public"));
app.set('views', path.join(__dirname, 'public/views'));
app.set('img', path.join(__dirname, 'public/img'));
app.set('js', path.join(__dirname, 'public/js'));
app.set('css', path.join(__dirname, 'public/css'));
app.set('controllers', path.join(__dirname, '/public/controllers'));
app.set('db', path.join(__dirname, '/public/db'));
app.engine('handlebars', exphbs({
defaultLayout: 'home',
layoutsDir: path.join(__dirname, '/public/views')
}))
app.set('view engine', 'handlebars');
app.use(require('./public/controllers'))
console.log(`listening on port ... ${port}`)
app.listen(port);

The reason you are getting Uncaught ReferenceError: require is not defined is because your bundles contains require keyword, which is undefined in the browser?
Why do they contain require?
Because you use nodeExternals from webpack-node-externals
From their docs:
All node modules will no longer be bundled but will be left as require('module').

Related

Webpack building the wrong file?

So I've a bug I've been chasing all day, and I've narrowed it down to my webpack config (I think).
I run my app locally using webpack server and index.html is displayed correctly (with the relevant script file).
I build my project locally, right-click index.html and open with live-server, and index.html is displayed correctly
I upload my files to my server, get Express to return index.html, and it returns index.html (I can tell because the script tag refers to index.js and the title tab says home), but the content is that of admin.html
Deleting the contents of index.html on the server to a simple page confirms (imo) that it isn't an issue of Express serving the wrong file
So it must be a webpack issue, right?
What I don't understand is why webpack server and live server display the content correctly, but the (apparently) same file doesn't in production. I probably don't have the correct webpack.prod.js config settings (they're basically empty), but I'm not experienced enough to spot the issue, so would appreciate if someone has the time to look
My file structure locally:
|-dist
|
|-src
| |-- assets
| |-- css
| |-- js
| |-- admin.html
| |-- index.html
|
|-webpack.common.js
|-webpack.dev.js
|-webpack.prod.js
|-package.json
|-// more config files
// webpack.common.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
index: './src/js/controllers/indexController.js',
admin: './src/js/controllers/adminController.js'
},
output: {
filename: '[name].bundle.[chunkhash].js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
module: {
rules: [
{
test:/\.css$/i,
use: ['style-loader', 'css-loader', 'postcss-loader']
},
{
test: /\.js$/i,
use: ['babel-loader'],
exclude: /node_modules/,
},
{
test: /\.(png|svg|jpg|jpeg|gif|webp)$/i,
type: 'asset/resource'
},
]
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/index.html',
chunks: ['index']
}),
new HtmlWebpackPlugin({
filename: 'admin.html',
template: './src/admin.html',
chunks: ['admin']
})
]
}
// webpack.dev.js
const path = require('path');
const {merge} = require('webpack-merge');
const common = require('./webpack.common');
module.exports = merge(common, {
mode: "development",
devServer: {
static: {
directory: path.resolve(__dirname, 'dist'),
},
port: 4600,
open: {
app: {
name: 'chrome',
},
},
hot: true,
compress: true,
historyApiFallback: true,
watchFiles: ["src/**/*"]
},
});
// webpack.prod.js
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
});
*Edit I still think the server is sending the correct html file because the title and js src reference index, however the source now does look wrong (it has been correct in the past):
// var/www/my-site/express-app/public/html/index.html
<script defer="defer" src="./src/js/controllers/index.bundle.0bb3ac28e5969d907928.js"></script>
But I've no idea why the file was previously displaying another page's html (despite me removing that page, admin.html, entirely). It's no longer doing that, just complaining about the path to the file - which is progress.
Server file structure
// var/www/my-site/express-app
|-node_modules
|
|-public
| |-- assets
| |-- css
| |-- js
| |-- admin.html
| |-- index.html
|
|-package-lock.json
|-package.json
|-app.js
// app.js
const express = require('express');
const path = require('path');
const app = express();
const port = 3000;
app.use(express.static('public'));
app.get('/index', (req, res, next) => {
console.log('path:', path.join(__dirname, 'public', 'index.html'));
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
app.get('/', (req, res, next) => {
console.log('path:', path.join(__dirname, 'public', 'index.html'));
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
app.use((error, req, res, next) => {
res.status(500).json({msg: 'Please contact your web administrator'});
});
app.listen(port, () => console.log(`Listening on port ${port}`));

How can I use Express.js with webpack?

I'm trying to set up a webpack server with Express.
When I use a simple script, such as the following:
document.getElementById('testing').innerHTML = "It's a test";
if (module.hot) {
module.hot.accept();
}
The server works fine, both from the same machine and from other devices in the same network.
However, when I try to require Express, it breaks with 25 errors.
Here's what I've got:
webpack.config.js
const path = require('path');
module.exports = {
entry: './app/serverTest.js',
mode: 'development',
output: {
filename: 'bundled.js',
path: path.resolve(__dirname, 'app')
},
devServer: {
before: (app, server) => {
server._watch('./app/**/*.html');
},
contentBase: path.join(__dirname, 'app'),
hot: true,
port: 4000,
host: '0.0.0.0'
},
}
serverTest.js
let express = require('express');
let app = express();
alert('This is a test');
I'm not even using the Express code. Just by requiring it, I get errors.
Here's the VSCode console logging: https://justpaste.it/342o0 (external link because it's very long)

Uncaught SyntaxError: Cannot use import statement outside a module when using express

I am trying to deploy a website with a basic express server(inexperienced with it obviously) when I use a node dev server it works fine but when I use node server.js i get this error
Uncaught SyntaxError: Cannot use import statement outside a module
So I have a main.js with imports as follows:
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import { defaults as defaultControls } from 'ol/control';
I have my basic server.js
const express = require('express');
const path = require('path');
const port = process.env.PORT || 3003;
const app = express();
app.use(express.static(__dirname));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, './frontend/index.html'));
});
app.listen(port);
Start script
"start": "node server.js",
and webpack config
module.exports = {
entry: './main.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: './main.js'
},
devtool: 'source-map',
devServer: {
port: 3003,
clientLogLevel: 'none',
stats: 'errors-only'
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
},
plugins: [
new CopyPlugin([{from: 'data', to: 'data'}]),
new HtmlPlugin({
template: './frontend/index.html'
})
]
};
folder structure
frontend -index.html
-page2.html
main.js
package.json
webpack
...

Using webpack with express and ejs for frontend and/or server

I am struggling a bit to find a solution to using webpack on the both the frontend and the server part of a nodejs project.
I am building an express solution with different API endpoints and a frontend that uses EJS for templating that will use these endpoints for data handling.
Basically what I am trying to achieve is to using webpack to compile my SCSS and JS on the frontend and also a solution that will compile EJS and inject the CSS and JS bundles into the frontend.
My current server.js
const express = require('express')
const formidable = require('express-formidable');
const session = require('express-session')
const bodyparser = require('body-parser')
const app = express()
const path = require('path');
const auth = require('./app/middleware/authorization/auth')
const upload = require('./app/middleware/filehandling/upload')
app.set('port', process.env.PORT || 8080);
app.set('view engine', 'ejs')
app.set('views', path.join('views'));
app.use(session({
secret: hash.getRandomString(16),
resave: true,
saveUninitialized: true
}))
app.use(express.json())
app.use('/public', express.static(path.resolve(__dirname, 'public')));
app.use(formidable());
app.use(passport.initialize());
app.use(passport.session());
app.use(bodyparser.urlencoded({ extended: true }))
app.use(bodyparser.json())
//DIFFERENT ROUTES DOWN HERE
app.listen(3000, () => {
console.log('listening on port 3000')
})
My folder structure is
public
- upload/
src
- scss/
- index.js
views
- partials/
- index.ejs
- login.ejs
I have a current webpack.config.dev.js that I am using for static HTML/CSS/JS project that are building and compiling SCSS and JS into bundles.
const path = require('path');
const webpack = require('webpack');
const HTMLWebpackPlugin = require('html-webpack-plugin');
// const ExtractText = require('extract-text-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== 'production'
const dirNodeModules = 'node_modules';
const dirAPP = path.join(__dirname, 'src/app');
const dirAssets = path.join(__dirname, 'src/assets');
const packageJson = require('./package.json')
var config = {
entry: {
bundle: path.join(dirAPP, 'index')
},
resolve: {
modules: [
dirNodeModules,
dirAPP,
dirAssets
]
},
plugins: [
new webpack.DefinePlugin({
devMode: devMode
}),
new HTMLWebpackPlugin({
template: path.join('src', 'index.html'),
inject: true
}),
new MiniCssExtractPlugin({
filename: packageJson.name + '.[chunkhash].min.css'
})
],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: ['babel-loader', 'eslint-loader']
},
{
test: /\.(sa|sc|c)ss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
sourceMap: true,
config: {
path: 'postcss.config.js'
}
},
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: 'file?=name/fonts/[name].[ext]'
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [{
loader: 'file-loader',
options: {
name: '[name]-[hash:8].[ext]',
pluginPath: dirAssets + '/images/',
outputPath: dirAssets + '/images/'
}
}]
}]
}
}
module.exports = config;
And a webpack.config.build.js
const path = require('path');
const merge = require('webpack-merge');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const webpackConfig = require('./webpack.config');
const packageJson = require('./package.json');
module.exports = merge(webpackConfig, {
devtool: 'source-map',
output: {
path: path.join(__dirname, 'dist'),
filename: packageJson.name + '.[chunkhash].js'
},
plugins: [
new CleanWebpackPlugin(['dist'])
]
});
Which I call using
"dev": "cross-env NODE_ENV=dev webpack-dev-server --progress --mode development --config webpack.config.dev.js",
"build": "webpack -p --progress --mode production --config webpack.config.build.js"
I am a bit unsure how I can achieve this.

Refused to execute script from bundle.js because its MIME type

Hello I'm new to react and I'm trying to attach express framework with react, I followed this tutorial: https://blog.hellojs.org/setting-up-your-react-es6-development-environment-with-webpack-express-and-babel-e2a53994ade but when I run the server I'm getting the following error:
Failed to load resource: the server responded with a status of 404
(Not Found) localhost/:1
Refused to execute script from
'http://localhost:3000/dist/bundle.js' because its MIME type
('text/html') is not executable, and strict MIME type checking is
enabled.
I have been searching this error for two days now and I haven't find a solution. I think the problem is that the bundle.js is not being created by webpack, I would like to now why is this happening
My project directory is the following:
My config webpack file:
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: './client/index.js',
output: {
path: __dirname,
filename: 'bundle.js',
publicPath: '/client/assets/'
},
module: {
loaders: [
{
test: /\.(js|jsx)$/,
loader: 'babel-loader',
include: path.join(__dirname, 'client'),
exclude: /node_modules/,
query: {
presets: ['es2015', 'react', 'stage-0']
}
},
{
test: /\.css$/,
loader: 'css-loader'
}
]
},
};
server.js, where I create the express instance:
const path = require('path')
const express = require('express')
module.exports = {
app: function () {
const app = express();
const indexPath = path.join(__dirname, 'indexDep.html');
const publicPath = express.static(path.join(__dirname, '../dist'));
app.use('/dist', publicPath);
app.get('/', function (_, res) { res.sendFile(indexPath) });
return app;
}
}
And app.js, where I'm running the server:
const Server = require('./server.js')
const port = (process.env.PORT || 3000)
const app = Server.app()
if (process.env.NODE_ENV !== 'production') {
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpackHotMiddleware = require('webpack-hot-middleware')
const config = require('../webpack.dev.config.js')
const compiler = webpack(config)
app.use(webpackHotMiddleware(compiler))
app.use(webpackDevMiddleware(compiler, {
noInfo: true,
publicPath: config.output.publicPathdist
}))
}
app.listen(port)
console.log(`Listening at http://localhost:${port}`)
Try this:
// server.js
"use strict"
const path = require('path')
const express = require('express')
module.exports = {
app(init) {
const app = express()
const indexPath = path.join(__dirname, 'indexDep.html')
const publicPath = express.static(path.join(__dirname, '../dist'))
if (init != null) init(app)
app.use('/dist', publicPath)
app.get('/', function (_, res) { res.sendFile(indexPath) })
return app
},
}
// app.js
const Server = require('./server.js')
const port = (process.env.PORT || 3000)
Server.app(app => {
if (process.env.NODE_ENV !== 'production') {
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpackHotMiddleware = require('webpack-hot-middleware')
const config = require('../webpack.dev.config.js')
const compiler = webpack(config)
app.use(webpackHotMiddleware(compiler))
app.use(webpackDevMiddleware(compiler, {
noInfo: true,
publicPath: config.output.publicPathdist
}))
}
})
.listen(port)
console.log(`Listening at http://localhost:${port}`)
Specifically, what this does is two-fold:
It punts your initialization to before Express finally reads its catch-all routes for /dist and /. If you add the middleware after, you'll never see it set up in the first place.
It retains most of your other logic, without moving a lot of code. Closures are useful for that kind of thing, keeping logic where it belongs while still allowing others to let you hook into their logic.

Categories