Remove empty bundle file from the HTML template - javascript

I have a simple Webpack configuration to compile a static HTML file with the Bootstrap's CSS asset:
const path = require('path');
const glob = require('glob')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const PurgeCssPlugin = require('purgecss-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const mode = process.env.NODE_ENV || 'development';
const isProduction = 'production' === mode;
console.log(`Building mode: ${mode}`);
module.exports = {
mode: mode,
entry: './src/index.js',
output: {
path: path.resolve(__dirname, '..'),
filename: isProduction ? 'bundle.[contenthash].js' : 'bundle.js',
clean: false,
},
module: {
rules: [
{
test: /\.s[ac]ss$/i,
exclude: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'sass-loader',
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
inject: 'body',
template: 'index.ejs',
minify: isProduction,
}),
new MiniCssExtractPlugin({
filename: isProduction ? 'style.[contenthash].css' : 'style.css',
}),
new PurgeCssPlugin({
paths: glob.sync(path.join(__dirname, '..') + '/*', {nodir: true}),
}),
],
};
The src/index.js file is as simple as:
import "./scss/main.scss"
This configuration works really well, however since there're no JS files included, the generated bundle.js file is empty though it's still injected to the HTML template:
<script defer src="bundle.js"></script>
How can I remove this file completely from the template if it's empty?

Related

How to use webpack-dev-server for cshtml files in ASP.NET core 6 MVC

i use webpack in my asp.net core 6 mvc project.
I use webpack-dev-server to run the browser automatically. My question is, how can I see the changes on index.cshtml instead of index.html. (When I change the extension of the html file from html to cshtml, the browser cannot load the cshtml file)
in webpack.config.js:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TerserPlugin = require("terser-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");
module.exports = {
entry: {
opencv: './wwwroot/Source/example1.js',
},
mode: 'development',
devtool: 'inline-source-map',//baraye modiriate khataha
devServer: {//jahate webpack-dev-server(hmr bedoobe webpack-hot-middleware )
static: {
directory: path.join(__dirname,'/wwwroot/distt/' ),
publicPath: '/devserverdist4/',
},
compress: true,
port: 9003,
open: true,
},
plugins: [
new HtmlWebpackPlugin({
title: 'index1',
}),
new HtmlWebpackPlugin({
title: 'index2',
filename: 'index2.html',
}),
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
Popper: ['popper.js', 'default']
}),
new MiniCssExtractPlugin({
//filename: "allstyles_for_bonLarma.css",
filename: '[name].styles.css',
}),
new NodePolyfillPlugin(),//taze ezafe baraye erore fs
new webpack.DefinePlugin({
'process.env.ASSET_PATH': JSON.stringify(ASSET_PATH),
}),
],
output: {
filename: '[name].bundle.js',
path: path.join/*resolve*/(__dirname, '/wwwroot/dist/'),
publicPath: '/outputdist1/',
clean: true,
},
optimization: {
minimize: true,
minimizer: [new TerserPlugin(), new CssMinimizerPlugin(),],
},
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.js?$/,
use: {
loader: 'babel-loader', options: {
presets:
['#babel/preset-react', '#babel/preset-env']
}
}
},
]
},
resolve: { //taze ezafe baraye erore fs
fallback: {
fs: false,
},
}
};
I want to use the webpack-dev-server feature in my mvc project views that have cshtml extension
I dont think you can do that. Razor cshtml file need to have everything include in the view before you build and run your project so that it can build and transform cshtml to html.
HtmlWebpackPlugin only work with html so the only option you can choose is serve the html file in your .net core project.
Update
You don't need to use webpack-dev-server, it's more convenient to use nuget package:
Add Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation NuGet package to the project.
Add the following in Program.cs:
builder.Services.AddControllersWithViews().AddRazorRuntimeCompilation();

Bundle browser library on node environment

So basically the problem is described in a title. I'm trying to use a library(quill) that runs only in browser environment and in my project I have two webpack configs, one for a client build and second for a server. After adding this library server build is failing because of this line. So the problem here is my webpack doesn't look at node_modules folder and not converting this line for babel. So I used webpackNodeExternals and added this file in whitelist. After that my build failing because quill uses document somewhere in its code, and of course document is not defined in node env. So far I tried ProvidePlugin and defined document from jsdom, but then somewhere in quill code base they are using this.textNode = document.createTextNode(Cursor.CONTENTS); and my build is failing again. probably because document from jsdom is not the same as browser's window.document...
The solution I'm looking for is how to tell my server not to build this library and its dependecies at all, or somehow replace it with something else only in server build. I don't need this on server side at all, only in client build which is passing correctly
EDIT: Added webpack.config.js that used for server build
const path = require('path')
const webpack = require('webpack')
const dotenv = require('dotenv')
const webpackNodeExternals = require('webpack-node-externals')
const CleanWebpackPlugin = require('clean-webpack-plugin')
const TerserWebpackPlugin = require('terser-webpack-plugin')
const StartServerPlugin = require('start-server-webpack-plugin')
const CaseSensetivePathsWebpackPlugin = require('case-sensitive-paths-webpack-plugin')
const dotenvPath = process.env.DOTENV_PATH
? path.resolve(process.cwd(), process.env.DOTENV_PATH)
: path.resolve(process.cwd(), '.env')
const { parsed: envs = {} } = dotenv.config({ path: dotenvPath })
console.info(
`Environment was read from '${path.relative(process.cwd(), dotenvPath)}'`
)
const OUTPUT_PATH = path.resolve(__dirname, './build')
module.exports = {
name: 'webClient/server',
bail: process.env.NODE_ENV === 'production',
mode: process.env.NODE_ENV,
entry: [
'#babel/polyfill',
process.env.NODE_ENV === 'development' && 'webpack/hot/poll?666',
'./server'
].filter(Boolean),
output: {
path: OUTPUT_PATH,
filename: 'server.js'
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|scripts)/,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: process.env.NODE_ENV === 'development'
}
},
{
loader: 'eslint-loader',
options: {
cache: process.env.NODE_ENV === 'development',
rules: {
'prettier/prettier': 'off'
}
}
}
]
},
{
test: /\.css$/,
exclude: /(node_modules|scripts)/,
use: [
{
loader: 'css-loader',
options: {
url: false,
import: false,
modules: true,
localIdentName: '[local]___[hash:base64:5]',
exportOnlyLocals: true,
importLoaders: 1
}
},
'postcss-loader'
]
}
]
},
devtool: 'source-map',
watch:
process.env.NODE_ENV === 'development',
stats: {
chunks: false,
colors: true
},
target: 'node',
externals: [
webpackNodeExternals({
whitelist: ['webpack/hot/poll?666']
})
],
optimization: {
minimizer: [
process.env.NODE_ENV === 'production' &&
new TerserWebpackPlugin({
parallel: true,
sourceMap: true
})
].filter(Boolean)
},
plugins: [
new CleanWebpackPlugin([OUTPUT_PATH]),
process.env.NODE_ENV === 'development' &&
new webpack.HotModuleReplacementPlugin(),
process.env.NODE_ENV === 'development' &&
Boolean(process.env.SERVER_WATCH) &&
new StartServerPlugin({
name: 'server.js',
nodeArgs: ['--inspect']
}),
new CaseSensetivePathsWebpackPlugin(),
new webpack.DefinePlugin({
'process.env': Object.assign(
{
SERVER: true
},
Object.keys(envs).reduce(
(destination, key) =>
Object.assign(destination, {
[key]: JSON.stringify(envs[key])
}),
{}
)
)
})
].filter(Boolean),
resolve: {
modules: ['node_modules', 'src'],
extensions: ['.js', '.jsx', '.json', '.css']
}
}

How to get webpack hot reload to detect changes in pug + express?

I have an Express app with pug and stylus. I've configured the HMR middleware and it reloads on stylus changes but not for pug changes.
I'm wondering if I'm missing a specific configuration. I also tried adding the pug-html-loader but that didn't work either.
// server.js
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
const webpackDevMiddleware = require('./hmr').dev;
const webpackHotMiddleware = require('./hmr').hot;
app.use(webpackDevMiddleware);
app.use(webpackHotMiddleware);
// hmr.js
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const webpack = require('webpack');
const webpackConfig = require('./webpack.config.js');
const compiler = webpack(webpackConfig);
exports.dev = webpackDevMiddleware(compiler, {
noInfo: true,
filename: webpackConfig.output.filename,
publicPath: webpackConfig.output.publicPath,
stats: {
colors: true
}
});
exports.hot = webpackHotMiddleware(compiler, {
log: console.log,
path: '/__webpack_hmr',
heartbeat: 10000
});
// webpack.config.js
const javascriptRule = {
test: /\.js$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['env']
}
}
]
};
const stylesRule = {
test: /\.styl$/,
use: ['style-loader', 'css-loader', 'stylus-loader']
};
module.exports = {
context: path.join(__dirname, 'javascripts'),
entry: [
'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000',
'./index.js'
],
devtool: 'source-map',
output: {
path: path.join(__dirname, 'public', 'dist'),
filename: 'bundle.js',
publicPath: '/dist/',
library: 'aux'
},
module: {
rules: [javascriptRule, stylesRule]
},
plugins: [new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin()]
}
You need install raw-loader: https://webpack.js.org/loaders/raw-loader/
Webpack 3 config:
module: {
rules: [
{
test: /\.pug$/,
use: [
{loader: 'raw-loader'},
{loader: 'pug-html-loader'}
]
}
]
},
plugins: [
// Templates HTML
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/templates/index.pug'
}),
new HtmlWebpackPlugin({
filename: 'contact.html',
template: './src/templates/contact.pug'
}),
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin()
]
app.js
// import all template pug
import 'raw-loader!./templates/index.pug'
import 'raw-loader!./templates/contact.pug'
...
That makes webpack listen the changes in the pug files, but it also adds this js code to the bundle.js, then you need to process app.js to clean the bundle.js.

How to Hot Reload Sass Using Webpack 2?

I'm working on setting up a React application that uses Webpack2, webpack-dev-middleware and HMR for development. Whenever I make a change on a React component, it updates in the browser as intended. The issue I am running into is that when I modify my .scss files, the browser does not update. What happens instead, is that in the console it gives me the following:
[HMR] bundle rebuilding
client.js:207 [HMR] bundle rebuilt in 1567ms
process-update.js:27 [HMR] Checking for updates on the server...
process-update.js:98 [HMR] Nothing hot updated.
process-update.js:107 [HMR] App is up to date.
After this, when I refresh the page, my style changes appear. I'm not entirely sure what's going on or where the issue stems from but would like some help and clarification.Below is my setup:
Webpack.config.js
var webpack = require('webpack');
var path = require('path');
var autoprefixer = require('autoprefixer');
var DashboardPlugin = require('webpack-dashboard/plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var argv = require('yargs').argv;
const config = {};
// This configured production
if (argv.p) {
config.entry = [
'./src/client/scripts/index',
'./src/client/scripts/utils/index',
'./src/client/styles/index.scss'
]
config.plugins = [
new DashboardPlugin(),
new ExtractTextPlugin({
filename: 'bundle.css',
allChunks: true
}),
]
}
else {
config.entry = [
'react-hot-loader/patch',
'webpack-hot-middleware/client',
'./src/client/scripts/index',
'./src/client/scripts/utils/index',
'./src/client/styles/index.scss'
]
config.plugins = [
new DashboardPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new webpack.NamedModulesPlugin(),
new ExtractTextPlugin({
filename: 'bundle.css',
allChunks: true
})
]
}
module.exports = {
entry: config.entry,
output: {
path: path.join(__dirname, 'src', 'client', 'static'),
filename: 'bundle.js',
publicPath: '/static/'
},
devtool: 'inline-source-map',
devServer: {
hot: true,
contentBase: path.resolve(__dirname, 'src', 'client', 'static'),
publicPath: (__dirname, 'src', 'client', 'static')
},
plugins: config.plugins,
module: {
rules: [
{
test: /\.js?$/,
exclude: /(node_modules|bower_components)/,
include: path.join(__dirname, 'src'),
use: [
{
loader: 'babel-loader',
query: {
presets: ['react', ['es2015', { 'modules': false }], 'stage-0'],
plugins: ['react-hot-loader/babel', 'react-html-attrs', 'transform-class-properties', 'transform-decorators-legacy'],
}
}
]
},
{
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
use: [
{
loader: 'url-loader?limit=100000'
}
],
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'sass-loader']
})
}
]
}
};
Server.js using webpack-dev-middleware
const router = Router();
const clientDir = resolve(`${__dirname}/../../client`);
if (isDev()) {
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpack = require('webpack')
const webpackConfig = require('../../../webpack.config')
const webpackHotMiddleware = require('webpack-hot-middleware')
const compiler = webpack(webpackConfig)
// This compiles our app using webpack
router.use(webpackDevMiddleware(compiler, {
publicPath: webpackConfig.output.publicPath,
noInfo: true
}))
// This connects our app to HMR using the middleware
router.use(webpackHotMiddleware(compiler))
}
router.use(express.static(clientDir));
export default router
index.js on client side
import React from 'react'
import ReactDOM from 'react-dom'
import { AppContainer } from 'react-hot-loader'
import App from './App'
const root = document.querySelector('.root');
// Wraps our App in AppContainer
const render = (Component) => {
ReactDOM.render(
<AppContainer>
<Component/>
</AppContainer>,
root
);
};
// Renders our application
render(App);
// This checks if a component has been updated
// It then accepts the changes and replaced the module.
// It's only checking if JS has been changed...
// #TODO - it only works for JS not CSS.
// I think this is an issue with webpack not
// recognizing bundle.css as a dependency?
if (module.hot) {
module.hot.accept();
}
You're using extract-text-webpack-plugin and after webpack rebuilds the bundle the webpack-dev-middleware thinks that nothing changed, because the corresponding module in your bundle representing the CSS is empty as its content has been extracted.
You need to disable extract-text-webpack-plugin in development to get HMR. You can use the disable option and it will fallback to the style-loader, which injects the <style> tags.
new ExtractTextPlugin({
filename: 'bundle.css',
allChunks: true,
disable: true
})
Instead of having to define two versions of the plugin you can use environment variables like NODE_ENV=production and use it in the plugin:
new ExtractTextPlugin({
filename: 'bundle.css',
allChunks: true,
disable: process.env.NODE_ENV !== 'production'
})

How to version CSS file in Webpack and update manifest?

I have a webpack config that has multiple JS entry points. In one of those entry points, I am requiring my styles: require('../sass/app.scss'); and then using a loader to extract the styles into another file app.css.
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader!postcss-loader!sass-loader',
})
And that is working great. Of course, we are having issues with old styles being served when we deploy because they are not being versioned like our JS. I have been searching around for a few hours on how to do this and I cannot find a source on how to not only version the CSS, but also get a manifest file for the CSS. I tried creating a new instance of the versioning plugin that I am using, but it only created a manifest for the JS files. I am assuming that since I only have an output for JS that is the reason for this. Anyhow, here is my webpack.config.js:
const webpack = require('webpack');
const autoprefixer = require('autoprefixer');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const CommonsPlugin = require('webpack/lib/optimize/CommonsChunkPlugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const path = require('path');
const VersioningPlugin = require('versioning-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const routes = require('./resources/assets/js/routes');
module.exports = {
entry: routes,
devtool: 'eval-source-map',
output: {
path: path.join(__dirname, 'public/js'),
filename: '[name].[chunkhash:6].js'
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel-loader?presets[]=env',
exclude: path.resolve(__dirname, 'node_modules/')
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader!postcss-loader!sass-loader',
})
}
],
},
plugins: [
new CommonsPlugin({
minChunks: 3,
name: 'common'
}),
new BrowserSyncPlugin({
host: 'localhost',
port: 3000,
proxy: 'napaautocarepro.dev',
files: [
'public/css/app.css',
{
match: ['public/js/*.js', 'app/**/**/*.php', 'resources/views/**/**/*.php'],
fn: function(event, file) {
this.reload();
}
}
]
}, {
injectChanges: true,
reload: false
}),
new ExtractTextPlugin('../css/app.css'),
new VersioningPlugin({
cleanup: true,
basePath: 'js/',
manifestPath: path.join(__dirname, 'public/manifest.json')
}),
new WebpackMd5Hash()
]
};
And here is my weback.prod.config.js:
const config = require('./webpack.config');
const path = require('path');
const webpack = require('webpack');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
config.plugins.unshift(
new CleanWebpackPlugin(['js', 'css'], {
root: path.join(__dirname, 'public'),
verbose: true,
dry: false,
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
comments: false,
sourceMap: true
}),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require('cssnano'),
canPrint: true,
cssProcessorOptions: { discardComments: { removeAll: true } }
})
);
module.exports = config;
How in the world can I version my CSS file and get it into a manifest so I can autoload the correct version?
Add [chunkhash] to the name of the file, something like:
plugins: [
//...
new ExtractTextPlugin('../css/app.[chunkhash].css'),
//...
]
(from https://github.com/webpack-contrib/extract-text-webpack-plugin#options )

Categories

Resources