HtmlWebpackPlugin & CompressionPlugin not . adding gzip to the bundle - javascript

I have a React app, served via ExpressJS. I have configured Webpack to create .gz assets.
However HtmlWebpackPlugin creates the bundle in my index.html as a .js file.
I assume this is because in the output prop in my webpack.prod.js I have the filename with a .js extention.
How can I configure this to return the .gz extension when supported?
Express App
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.resolve(__dirname, '../dist')));
app.get('*.js', function(req, res, next) {
req.url = req.url + '.gz';
res.set('Content-Encoding', 'gzip');
next();
});
app.get('/healthz', (req, res) => res.send('OK'));
app.get('*', (req, res) =>
res.sendFile(path.resolve(__dirname, '../dist/index.html'))
);
const PORT = process.env.SERVER_PORT || 3000;
const HOST = process.env.SERVER_HOST || '127.0.0.1';
app.listen(PORT);
console.log(`API started on ${HOST}:${PORT}`);
webpack.common.js
const commonPaths = require('../common-paths');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
context: commonPaths.appPath,
entry: './index.jsx',
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [
{ test: /\.(jsx?)$/, exclude: /node_modules/, use: ['babel-loader'] }
]
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: 'initial',
test: 'vendor',
name: 'vendor',
enforce: true
}
}
}
},
plugins: [
new CompressionPlugin({
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8
}),
new HtmlWebpackPlugin({
title: 'Web App',
template: commonPaths.projectRoot + '/public/index.html',
inject: 'body'
})
]
};
webpack.prod.js
const commonPaths = require('../common-paths');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
devtool: 'source-map',
mode: 'production',
output: {
filename: 'static/[name].[hash].min.js',
path: commonPaths.outputPath
},
plugins: [
new ExtractTextPlugin({
filename: 'static/styles.[hash].min.css',
allChunks: true
})
]
};
I have also tried the following in my Express App incase it was failing in serving the files...
const express = require('express');
const path = require('path');
const app = express();
app.use(
express.static(path.resolve(__dirname, '../dist'), {
index: false,
fallthrough: true,
setHeaders: (res) => {
res.set('Content-Encoding', 'gzip');
}
})
);
app.get('/healthz', (req, res) => res.send('OK'));
app.get('*', (req, res) =>
res.sendFile(path.resolve(__dirname, '../dist/index.html'))
);
const PORT = process.env.SERVER_PORT || 3000;
const HOST = process.env.SERVER_HOST || '127.0.0.1';
app.listen(PORT);
console.log(`API started on ${HOST}:${PORT}`);

Related

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.

Custom static route not working

Hi I am trying to establish my project in react.
My Current project structure is
-public
--w
---dist
----bundle.js
---index.html
-server
--server.js
-src
--app.js
-webpack.config.js
-package.json
-.babelrc
I am using node js as server
I want my static files to called on localhost:port//w/
and api call on localhost:port//api/
I have tried manipulating server.js, routes, project structure and webpack.config but could not get success.
server.js
const express = require('express');
const path = require('path');
const app = express();
const port = 3000;
const publicPath = path.join(__dirname, '../public/w');
app.use(express.static(publicPath));
app.get('/w/*', (req, res) => {
console.log('Calling..');
res.sendFile(path.join(publicPath, 'index.html'));
})
app.get('/api/test', (req, res) => {
res.send("Hello");
})
app.listen(port, () => {
console.log(`Server is up on ${port}`);
})
webpack.config
const path = require('path');
module.exports = {
entry: './src/app.js',
output: {
path: path.join(__dirname, 'public', 'w', 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/
}
]
},
devtool: 'inline-source-map',
devServer: {
contentBase: path.join(__dirname, 'public', 'w'),
publicPath: '/dist/',
historyApiFallback: true
}
}
My routes
const AppRouter = (props) => {
return (
<BrowserRouter>
<div>
<Switch>
<Route path="/" component={Dashboard} />
<Route path="/w/resume-builder" component={ResumeBuilder} />
</Switch>
</div>
</BrowserRouter>
)
}
Can anyone suggest what should I do or What I am missing in it?
You have to do some restructure
-public
--dist
---bundle.js
--index.html
-server
--server.js
-src
--app.js
-webpack.config.js
-package.json
-.babelrc
Server.js
const express = require('express');
const path = require('path');
const app = express();
const port = 3000;
const publicPath = path.join(__dirname, '../public');
app.use(express.static(publicPath));
//keep all api before fallback
app.get('/api/test', (req, res) => {
res.send("Hello");
});
app.get('/w/*', (req, res) => {
console.log('Calling..');
res.sendFile(path.join(publicPath, 'index.html'));
});
app.listen(port, () => {
console.log(`Server is up on ${port}`);
});
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/app.js',
output: {
path: path.join(__dirname, 'public', 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/
}
]
},
devtool: 'inline-source-map',
devServer: {
contentBase: path.join(__dirname, 'public'),
publicPath: '/dist/',
historyApiFallback: true
}
}
You can keep your routes same.

How to connect secure on localhost through webpack

I have a webpack plugin as below, I want to user localhost secure , how can I do that ? I do not see any require('http') as in the nodejs server, how can I do that with this webpack configuration ?
Should I prepare some SSL certificate ? If so where should I use them ?
Here is webpack configuration for development
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors
? utils.createNotifierCallback()
: undefined
}))
resolve(devWebpackConfig)
}
})
})
devServer: {
https: true,
...
},

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.

Webpack dev middleware for all routes

I configured webpack dev middleware, when I go to index page / all works fine, otherwise page Not Found, how to make work dev server for all paths ?
const Koa = require('koa');
const webpack = require('webpack');
const devMiddleware = require('koa-webpack-dev-middleware')
const path = require('path');
const fs = require('fs');
const PORT = 3000;
const app = new Koa();
const config = require('./webpack.config');
const compiler = webpack(config);
app.use(devMiddleware(compiler, {
publicPath: config.output.publicPath,
historyApiFallback: true,
stats: { colors: true },
}));
app.listen(PORT, function () {
console.log(`Dev Server port: "${3000}"`);
});
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
},
devtool: 'inline-source-map',
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Output Management'
})
],
module: {
rules: [
{
test: /.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ['file-loader']
},{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: ['file-loader']
}
]
}
}

Categories