Please find my webpack config below:
const LinkTypePlugin = require('html-webpack-link-type-plugin').HtmlWebpackLinkTypePlugin;
const path = require('path');
const webpack = require('webpack');
const FileManagerPlugin = require('filemanager-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = function(env) {
const config = {};
config.entry = {
'apps/xyz': './apps/xyz/index.js',
};
config.mode = (env && env.NODE_ENV) || 'production';
config.output = {
path: path.resolve(__dirname, './dist'),
filename: './[name]/bundle.[hash].js',
};
if (config.mode === 'development') {
config.devtool = 'eval-source-map';
} else {
config.devtool = false;
}
config.module = {
rules: [
{
test: /\.jsx?$/,
exclude: /[\\/]node_modules[\\/]\.+/,
use: {
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
targets: 'defaults',
useBuiltIns: 'entry',
corejs: 3,
},
],
'@babel/preset-react',
],
plugins: [
'@babel/plugin-proposal-class-properties',
...(config.mode === 'production'
? [['transform-react-remove-prop-types', { removeImport: true }]]
: []),
],
},
},
},
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
// loader for processing sass templates used by react files
{
test: /\.(sass|scss|css)$/,
exclude: /[\\/]node_modules[\\/]\.+/,
use: [
config.mode === 'production'
? {
loader: MiniCssExtractPlugin.loader,
options: { publicPath: '../' },
}
: 'style-loader',
'css-loader',
'sass-loader',
],
},
{
test: /\.(jpe?g|png|gif|svg|bmp)$/i,
loader: 'file-loader',
options: {
name: './[path][hash].[ext]',
useRelativePaths: true,
},
},
],
};
config.resolve = {
extensions: ['.tsx', '.ts', '.js'],
alias: {
src: path.resolve(__dirname),
},
};
// Configure plugins
config.plugins = [
new CleanWebpackPlugin(),
new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /en-gb/),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './apps/xyz/index.html'),
filename: 'apps/xyz/index.html',
chunks: ['apps/xyz'],
minify: {
removeStyleLinkTypeAttributes: false,
removeScriptTypeAttributes: false,
collapseWhitespace: true,
removeComments: true,
removeRedundantAttributes: true,
useShortDoctype: true,
},
}),
new MiniCssExtractPlugin({
filename: './[name]/main.[hash].css',
chunkFilename: './[name]/main-[id].[hash].css',
insert: 'text/css',
linkType: 'text/css',
}),
new LinkTypePlugin({
'**/*.css': 'text/css',
}),
new FileManagerPlugin({
onEnd: [
{
delete: ['../extension/public'],
copy: [
{
source: './dist/',
destination: '../extension/public/',
},
],
},
],
}),
];
// Adding new version of uglifyjs plugin as required by other packages
if (env && env.NODE_ENV === 'production') {
config.plugins.push(new UglifyJSPlugin());
}
return config;
};
The index.html
file generated has the CSS attached but without type=text/css
which I need for strict type compatibility. Please help.
The issue was the glob I specified in LinkTypePlugin **/*.css
is not an all-cover scenario. I changed it to ./**/*.css
and it works!
The key is to look at the generated index.html
. The injected links
's href
or src
will help in defining your glob pattern.
In cases where the generated files' path is not very straightforward, MiniCssExtractPlugin
isn't able to do much.