Webpack with sourcemap can't resolve variables in production mode - javascript

I would like to generate source maps for our production build with Webpack. I managed to generate it, but when I stop on a breakpoint in the debugger, variables are not resolved:
What am I doing wrong? How can I generate a source map that lets the chrome devtools resolve the variables once I stopped on a breakpoint in the debugger?
These are my webpack configurations:
webpack.config.js:
const path = require('path');
const ROOT = path.resolve( __dirname, 'src/main/resources/packedbundle' );
const HtmlWebpackPlugin = require('html-webpack-plugin');
const LoaderOptionsPlugin = require('webpack/lib/LoaderOptionsPlugin');
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
context: ROOT,
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
exclude: /node_modules/,
use: [
{
loader: 'eslint-loader',
options: {
failOnError: true,
quiet: true
}
}
],
enforce: 'pre'
},
{
test: /\.ts$/,
exclude: [ /node_modules/ ],
use: [
'ng-annotate-loader',
'awesome-typescript-loader'
]
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'sass-loader'],
publicPath: '../'
}),
},
{
test: /\.(jpg|png|gif)$/,
use: 'file-loader'
},
{
test: /\.(svg|woff|woff2|eot|ttf)$/,
use: 'file-loader?outputPath=fonts/'
},
{
test: /.html$/,
exclude: /index.html$/,
use: 'html-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: 'AngularJS - Webpack',
template: 'index.html',
inject: true
}),
new LoaderOptionsPlugin({
debug: true
}),
new ExtractTextPlugin('css/style.css')
],
entry: './index.ts'
};
webpack-prd.config.js:
const path = require('path');
const webpackMerge = require('webpack-merge');
const commonConfig = require('./webpack.config.js');
const DESTINATION = path.resolve( __dirname, 'dist/packedbundle' );
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = webpackMerge(commonConfig, {
devtool: 'module-source-map',
mode: 'production',
output: {
path: DESTINATION,
filename: 'js/[name]-bundle-[chunkhash].js'
},
optimization: {
minimizer: [
new UglifyJsPlugin({
sourceMap: true
})
]
}
});
package.json:
{
"name": "com.avon.maps.packedbundle.webcontent",
"version": "1.0.0",
"description": "Packed bundle creation screen frontend",
"main": "index.js",
"scripts": {
"prestart": "rimraf dist",
"start": "node node/node_modules/npm/bin/npx-cli.js check-node-version --package && webpack --config webpack-dev.config.js",
"prebuild": "rimraf dist",
"build": "node node/node_modules/npm/bin/npx-cli.js check-node-version --package && webpack --config webpack-prd.config.js",
"test": "mocha -r ts-node/register -r ignore-styles -r jsdom-global/register __tests__/**/*.spec.ts"
},
"author": "BlackBelt",
"private": true,
"engines": {
"node": "11.10.0"
},
"devDependencies": {
"#types/angular": "1.6.51",
"#types/angular-loading-bar": "0.0.35",
"#types/chai": "4.1.7",
"#types/core-js": "2.5.0",
"#types/jquery": "3.3.29",
"#types/kendo-ui": "2019.1.1",
"#types/mocha": "5.2.6",
"#types/node": "10.12.0",
"#types/underscore": "1.8.13",
"#types/webpack-env": "1.13.6",
"#typescript-eslint/eslint-plugin": "1.6.0",
"#typescript-eslint/parser": "1.6.0",
"acorn": "6.1.1",
"awesome-typescript-loader": "5.2.1",
"chai": "4.2.0",
"check-node-version": "3.2.0",
"css-loader": "1.0.0",
"eslint": "5.16.0",
"eslint-config-airbnb-base": "13.1.0",
"eslint-loader": "2.1.2",
"eslint-plugin-import": "2.16.0",
"extract-text-webpack-plugin": "v4.0.0-beta.0",
"file-loader": "2.0.0",
"html-loader": "0.5.5",
"html-webpack-plugin": "3.2.0",
"ignore-styles": "5.0.1",
"istanbul-instrumenter-loader": "3.0.1",
"jsdom": "14.0.0",
"jsdom-global": "3.0.2",
"mocha": "6.1.2",
"ng-annotate-loader": "0.6.1",
"node-sass": "4.11.0",
"rimraf": "2.6.2",
"sass-loader": "7.1.0",
"style-loader": "0.23.1",
"ts-node": "8.0.3",
"typescript": "3.4.2",
"uglifyjs-webpack-plugin": "2.0.1",
"webpack": "4.23.1",
"webpack-cli": "3.1.2",
"webpack-merge": "4.1.4"
},
"dependencies": {
"angular": "1.7.5",
"core-js": "3.0.1",
"growl": "1.10.5",
"jquery": "3.3.1",
"underscore": "1.9.1"
}
}
I cannot share the source code, but I used this angularjs webpack starter project to start mine.

Issues with invalid sourcemaps in Webpack and terser-webpack-plugin are addressed starting with webpack 4.39.2 and terser-webpack-plugin 1.4.0.
v4.39.0 release log:
webpack-sources + terser-webpack-plugin comes with quality optimizations for SourceMaps
There was an additional issue, whose fix was published later. It was included for webpack-sources v1.4.2/webpack 4.39.2. In conclusion 4.39.2or latest version is the one to go.
Details
Sourcemaps in production mode seem to work as expected in most cases now. Unfortunately, if you have non trivial code transformations like inlining of functions (that exist in source code, but are dissolved from webpack) in the course of uglyfying/minification/optimization, breakpoints sometimes still don't get mapped well. Part of the reason is, that the sourcemap spec is vague concerning those aspects.

Related

Webpack: How to rewrie URL in .css

For 3 days straight I am having a trouble to setup Webpack for staging purposes.
The goal is to rewrite url of assets in final .css file (frontend.css) like this:
Let's say that in .scss file I have:
background: url('/assets/image.png') (this works for dev and prod)
and in final outputted .css file for staging, I want it to be:
background: url('https://stage.domain.com/staging/project-name/assets/image.png')
I have script npm run stage, that build js. and .css only for staging puposes.
It creates stage dir on root with two files frontened-bundle.js and frontend.css. (see bottom of "Files structure" screenshot).
I tried to rewrite url with resolve-url-loader with root parameter, but I cant get it working.
publicPath is also ignored.
I am not sure what I am doing wrong.
Please point me in right direction.
Files structure:
webpack.stage.js:
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const BrowserSyncPlugin = require('browser-sync-webpack-plugin');
const StyleLintPlugin = require('stylelint-webpack-plugin');
const public_path = 'https://stage.domain.com/staging/project-name/'
module.exports = {
context: __dirname,
entry: {
frontend: [
'./src/js/index.js',
'./src/scss/main.scss'
],
// customizer: './src/customizer.js'
},
resolve: {
extensions: ['.ts', '.js', '.jsx', '.scss', '...',],
},
output: {
path: path.resolve(__dirname, 'stage'),
publicPath: public_path,
filename: '[name]-bundle.js'
},
mode: 'production',
// devtool: 'cheap-eval-source-map',
module: {
rules: [
{
enforce: 'pre',
exclude: /node_modules/,
test: /\.jsx$/,
loader: 'eslint-loader'
},
{
test: /\.jsx?$/,
loader: 'babel-loader'
},
{
test: /\.s?css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: public_path,
sourceMap: true
}
},
{
loader: 'css-loader',
options: {
url: false,
sourceMap: true
}
},
{
loader: 'resolve-url-loader',
options: {
// root: path.join(__dirname, './'), // returns url("../../assets/assets/fonts/NewYork.woff2")
// root: '/', // returns url('../../../../../../assets/fonts/NewYork.woff2')
// root: './', // returns url('../../assets/fonts/NewYork.woff2')
attempts: 1,
debug: true,
sourceMap: true,
publicPath: public_path,
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
},
]
},
{
test: /\.(ttf|woff|woff2|eot|jpe?g|png|svg|gif)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
// outputPath: '../',
publicPath: publicPath,
},
},
'img-loader',
'url-loader',
]
}
]
},
plugins: [
// new StyleLintPlugin(),
new MiniCssExtractPlugin({
filename: '[name].css'
}),
],
optimization: {
// minimizer: [new UglifyJsPlugin(), new OptimizeCssAssetsPlugin()]
}
};
package.json
{
"name": "project_name",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack --mode=production",
"dev": "webpack --watch",
"stage": "npm run clean && webpack --config webpack.stage.js -p --progress --profile",
"clean": "rm -rf stage"
},
"repository": {
"type": "git",
"url": ""
},
"keywords": [
"webpack"
],
"author": "",
"license": "ISC",
"bugs": {
"url": ""
},
"homepage": "",
"devDependencies": {
"#babel/cli": "^7.14.5",
"#babel/core": "^7.6.2",
"#babel/preset-env": "^7.6.2",
"autoprefixer": "^9.6.4",
"babel-eslint": "^10.0.3",
"babel-loader": "^8.0.6",
"browser-sync": "^2.27.4",
"browser-sync-webpack-plugin": "^2.2.2",
"css-loader": "^3.2.0",
"css-mqpacker": "^7.0.0",
"eslint": "^6.5.1",
"eslint-config-prettier": "^6.4.0",
"eslint-config-wordpress": "^2.0.0",
"eslint-loader": "^3.0.2",
"eslint-plugin-prettier": "^3.1.1",
"extract-text-webpack-plugin": "^3.0.2",
"file-loader": "^4.2.0",
"img-loader": "^3.0.1",
"mini-css-extract-plugin": "^0.8.0",
"node-sass": "^4.14.1",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"postcss-loader": "^3.0.0",
"prettier": "^1.18.2",
"resolve-url-loader": "^4.0.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.0",
"stylelint": "^11.0.0",
"stylelint-config-recommended-scss": "^4.0.0",
"stylelint-config-wordpress": "^15.0.0",
"stylelint-order": "^3.1.1",
"stylelint-scss": "^3.11.1",
"stylelint-webpack-plugin": "^1.0.1",
"svg-sprite-loader": "^4.1.6",
"svgo": "^1.3.0",
"svgo-loader": "^2.2.1",
"uglifyjs-webpack-plugin": "^2.2.0",
"url-loader": "^4.1.1",
"webpack": "^4.41.0",
"webpack-cli": "^3.3.9",
"wp-pot-cli": "^1.5.0"
},
"dependencies": {
"#babel/polyfill": "^7.6.0",
"imagemin": "^8.0.0",
"jquery": "^3.6.0"
}
}
I've had this similar issue in the past, I tried the below from the docs,
const ASSET_PATH = process.env.ASSET_PATH || '/';
export default {
output: {
publicPath: ASSET_PATH,
},
plugins: [
// This makes it possible for us to safely use env vars on our code
new webpack.DefinePlugin({
'process.env.ASSET_PATH': JSON.stringify(ASSET_PATH),
}),
],
};
But actually, the one that worked perfectly for my issue is below, while the public path was the CDN link from where the assets were served
require('dotenv').config();
__webpack_public_path__ = config.publicPath // publicPath is process.env.ASSET_PATH || '/';
When you set the publicPath as "../" did you also try the useRelativePaths: true?
Ref:- https://github.com/webpack-contrib/file-loader#userelativepath

Webpack production mode does not minify js file

I created react app with by initializing webpack with npm init -y and then modified scripts and webpack config file manually. My file's contents are as below:
package.json
{
"name": "arw.ecahangirov",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack --mode development --watch ./frontend/src/index.js --output ./frontend/static/frontend/main.js",
"build": "webpack --mode production ./frontend/src/index.js --output ./static/frontend/main.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"#babel/core": "^7.5.5",
"#babel/preset-env": "^7.5.5",
"#babel/preset-react": "^7.0.0",
"babel-loader": "^8.0.6",
"babel-plugin-transform-class-properties": "^6.24.1",
"css-loader": "^3.2.0",
"prop-types": "^15.7.2",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"uglifyjs-webpack-plugin": "^2.2.0",
"weak-key": "^1.0.1",
"webpack": "^4.39.1",
"webpack-cli": "^3.3.6"
},
"dependencies": {
"axios": "^0.19.0",
"materialize-css": "^1.0.0-rc.2",
"moment": "^2.24.0",
"style-loader": "^1.0.0"
}
}
webpack.config.js
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
},
resolve: {
extensions: [".js", ".jsx", ".css"]
},
optimization: {
minimizer: [
new UglifyJsPlugin({
include: /\.js$/
})
]
}
};
Problem is that, when I run npm run build, webpack does not minify main.js file which is output. It results with 716kb file size and by opening output file I observe that file is multilined and also contains comments. Why webpack does not care of minifiying in this case, although I started it with --mode production?
You have to specify a minifier for css.
Load this at top of your webpack config file
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
To the rules block:
rules: [
//...
{
test: /\.(sa|sc|c)ss$/,
use: [{loader: MiniCssExtractPlugin.loader},
'css-loader',
'postcss-loader',
'sass-loader',
],
},
//...
]
To the optimization block:
optimization: {
minimizer: new OptimizeCSSAssetsPlugin({})
}
To the plugins block:
plugins: [
//...
new MiniCssExtractPlugin({
filename: [name].[hash].css',
chunkFilename: '[id].[hash].css',
}),
//...
]
You will need to load that plugins first
npm install --save-dev mini-css-extract-plugin
npm install --save-dev optimize-css-assets-webpack-plugin
You can find a working config here

webpack: custom style is missing after production build

I've updated my webpack file. Now it's won't apply my custom style to the main style bundle. No errors, classes with custom style just missing in bundle.
When I'm running build with development mode - everything is ok and my styles are exist in the bundle. Such happens only with production build.
I tried extract-text-webpack-plugin instead mini-css-extract-plugin but result is same - in prod build my styles are missing.
I'll be very apriciated for any kind of help.
Here is files:
webpack.config.js
const path = require('path');
const fs = require('fs');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const autoprefixer = require('autoprefixer');
const lessToJs = require('less-vars-to-js');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const publicPath = 'public';
const themeVariables = lessToJs(
fs.readFileSync(path.join(__dirname, './assets/style/ant-theme-vars.less'), 'utf8'),
);
module.exports = (env, options) => {
const mode = env ? env.mode : options.mode;
return {
entry: './assets/app.jsx',
output: {
path: path.resolve(__dirname, publicPath),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
options: {
plugins: [
autoprefixer({
browsers: 'last 2 version',
}),
],
},
},
{
loader: 'less-loader',
options: {
javascriptEnabled: true,
modifyVars: themeVariables,
},
},
],
},
{
test: /\.s?css$/,
exclude: [/node_modules/],
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
options: {
plugins: [
autoprefixer({
browsers: 'last 2 version',
}),
],
},
},
{
loader: 'sass-loader',
},
],
},
{
test: /\.jsx?$/,
exclude: [/node_modules/],
loaders: ['babel-loader'],
resolve: { extensions: ['.js', '.jsx'] },
},
{
test: /\.(png|jpg|jpeg|gif|svg|ico)$/,
exclude: [/node_modules/],
use: [
{
loader: 'file-loader',
options: {
name: 'img/[name].[ext',
},
},
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 70,
},
},
},
],
},
{
test: /\.(otf|ttf|woff|woff2)$/,
exclude: [/node_modules/],
loader: 'file-loader',
options: {
name: 'fonts/[name].[ext]',
},
},
],
},
plugins: [
new CleanWebpackPlugin(publicPath, {}),
new MiniCssExtractPlugin({
filename: 'bundle.css',
}),
new HtmlWebpackPlugin({
filename: 'index.html',
template: './assets/www/index.html',
}),
],
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
uglifyOptions: {
compress: true,
mangle: true,
warnings: false,
drop_console: true,
unsafe: true,
},
sourceMap: true,
}),
],
},
devServer: {
contentBase: path.join(__dirname),
compress: true,
port: 9000,
publicPath: '/',
historyApiFallback: true,
},
devtool: mode === 'development' ? 'cheap-inline-module-source-map' : '',
};
};
package.json
{
"name": "react-templates",
"version": "1.0.0",
"description": "",
"main": "bundle.js",
"sideEffects": false,
"scripts": {
"build": "webpack --progress --mode production",
"build-dev": "webpack -p --progress --mode development",
"start": "webpack-dev-server --mode production --open",
"eslint": "eslint . --ext .js --ext .jsx",
"stylelint": "stylelint assets/scss",
"deploy-current-branch-dev": "npm run build-dev && firebase deploy",
"deploy-dev": "git checkout -- . && git clean -fd && git checkout develop && git remote update && git pull && npm run build-dev && firebase deploy"
},
"author": "",
"license": "ISC",
"dependencies": {
"antd": "3.8.2",
"autoprefixer": "9.0.1",
"brace": "0.11.1",
"clean-webpack-plugin": "0.1.19",
"extract-text-webpack-plugin": "4.0.0-beta.0",
"fast-async": "^6.3.8",
"file-system": "2.2.2",
"firebase": "5.3.0",
"history": "4.7.2",
"html-webpack-plugin": "^3.2.0",
"less-vars-to-js": "1.3.0",
"lodash": "^4.17.11",
"mini-css-extract-plugin": "^0.4.3",
"moment": "2.22.2",
"optimize-css-assets-webpack-plugin": "5.0.0",
"prop-types": "15.6.2",
"react": "15.6.1",
"react-ace": "6.1.4",
"react-copy-to-clipboard": "5.0.1",
"react-dom": "15.6.1",
"react-favicon": "0.0.14",
"react-redux": "5.0.7",
"react-router": "4.3.1",
"react-router-dom": "4.3.1",
"react-sticky": "^6.0.3",
"redux": "4.0.0",
"redux-devtools-extension": "2.13.5",
"redux-logger": "3.0.6",
"redux-thunk": "2.3.0",
"uglifyjs-webpack-plugin": "^2.0.1",
"webpack": "^4.16.1",
"webpack-merge": "^4.1.4"
},
"devDependencies": {
"#babel/core": "^7.1.2",
"#babel/plugin-proposal-class-properties": "^7.1.0",
"#babel/preset-env": "^7.1.0",
"#babel/preset-react": "^7.0.0",
"babel-eslint": "8.2.6",
"babel-loader": "^8.0.4",
"babel-plugin-import": "^1.9.1",
"css-loader": "1.0.0",
"eslint": "4.19.1",
"eslint-config-airbnb": "17.0.0",
"eslint-plugin-import": "2.12.0",
"eslint-plugin-jsx-a11y": "6.0.3",
"eslint-plugin-react": "7.9.1",
"file-loader": "^2.0.0",
"husky": "1.0.0-rc.13",
"image-webpack-loader": "^4.3.1",
"less": "3.8.1",
"less-loader": "4.1.0",
"node-sass": "4.9.2",
"postcss-loader": "2.1.6",
"sass-loader": "7.0.3",
"style-loader": "0.21.0",
"stylelint": "9.4.0",
"stylelint-config-recommended": "2.1.0",
"webpack-bundle-analyzer": "^3.0.2",
"webpack-cli": "^3.1.0",
"webpack-dev-server": "^3.1.5"
},
"husky": {
"hooks": {
"pre-commit": "npm run eslint && npm run stylelint"
}
}
}
.babelrc
{
"presets": [
"#babel/preset-env",
"#babel/preset-react"
],
"plugins": [
"#babel/plugin-proposal-class-properties",
[
"import",
{
"libraryName": "antd",
"style": true
}
]
]
}
The probplem is sideEffects: false in my package.json file.
I found an issue on Github and there are some issues related to it.
Main reason I did it - I wanted to make a tree shank in my development mode. It worked as I expected but in production mode all my custom styles are missing. To solve this problem I just removed sideEffects: false. So I lost tree shank in dev mode (think it's not good solution to make it in development mode but however).

webpack4 css bundling not working for custom style names

I'm working on a making my own boilerplate for React using Webpack4 and have run the issue of my css file being bundled and not rendering specific custom styles. As you can see I am using the sass-loader compile all my .sass/scss files together and postcss-loader to autoprefixing, css-loader to load the compiled css files, MiniCssExtractPlugin.loader extracts CSS into separate files, and finally style-loader to inject my css. It does all this correctly buy doesn't seem to actually apply the styles. Could anybody explain why this occurs?
The repo can be found
here
webpack.config.js
/* Required Packages */
const webpack = require('webpack')
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
//entry to bundled js file
entry: [
'react-hot-loader/patch',
'./src/index.js'
],
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[hash].js' //output filename
},
//want to use the src/index.js file as entry point to bundle all of its imported files
module:{
rules:[
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
},
{
test: /\.scss$/,
use: [ 'style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader','sass-loader'],
exclude: ["node_modules"]
}
]
},
//webpack server hot module replacement
plugins: [
new CleanWebpackPlugin('dist', {}),
new MiniCssExtractPlugin({
filename: 'style.[hash].css',
}),
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: './src/index.html',
filename: 'index.html'
}),
new WebpackMd5Hash(),
new webpack.HotModuleReplacementPlugin()
],
resolve: {
extensions: ['*', '.js', '.jsx'] //array of extensions to compile js
},
devServer: {
contentBase: './dist',
hot: true
}
}
package.json
"scripts": {
"build": "webpack --mode production",
"dev": "webpack-dev-server --mode development --config ./webpack.config.js --open --hot --history-api-fallback"
},
"repository": {
"type": "git",
"url": "git+https://github.com/Nickadiemus/ns-react-boilerplate.git"
},
"author": "Nick Sladic",
"license": "MIT",
"bugs": {
"url": "https://github.com/Nickadiemus/ns-react-boilerplate/issues"
},
"homepage": "https://github.com/Nickadiemus/ns-react-boilerplate#readme",
"devDependencies": {
"autoprefixer": "^8.6.5",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-env": "^1.7.0",
"babel-preset-react": "^6.24.1",
"babel-preset-stage-2": "^6.24.1",
"clean-webpack-plugin": "^0.1.19",
"css-loader": "^1.0.0",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.4.1",
"node-sass": "^4.9.2",
"postcss-loader": "^2.1.6",
"react-hot-loader": "^4.3.3",
"sass-loader": "^7.0.3",
"style-loader": "^0.21.0",
"webpack": "^4.15.1",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.1.4",
"webpack-md5-hash": "0.0.6"
},
"dependencies": {
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-router-dom": "^4.3.1"
}
}
Use either 'style-loader' or MiniCssExtractPlugin.loader, not both:
const devMode = process.env.NODE_ENV !== 'production';
...
{
test: /\.scss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader'
],
exclude: ["node_modules"]
}
Source: mini-css-extract-plugin docs

Building for production causes errors in module package.json

Not sure what's going on, when I do a prod build ("cross-env NODE_ENV=production API_V=production npm run build") I get this error from from react-player:
ERROR in ./node_modules/react-player/lib/ReactPlayer.js Module build
failed: ReferenceError: Unknown plugin
"transform-es3-member-expression-literals" specified in
"C:\work\website\node_modules\react-player\package.json.env.production"
at 0, attempted to resolve relative to
"C:\work\website\node_modules\react-player"
I'm already excluding node_modules from babel:
rules: [
{
test: /\.js$/, // Transform all .js files required somewhere with Babel
exclude: /node_modules\/(?!(react-redux-toastr)\/).*/,
use: {
loader: 'babel-loader',
options: options.babelQuery,
},
},
As per request,
webpack.base.babel.js:
/**
* COMMON WEBPACK CONFIGURATION
*/
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = options => ({
mode: options.mode,
entry: options.entry,
output: Object.assign(
{
// Compile into js/build.js
path: path.resolve(process.cwd(), 'build'),
publicPath: '/',
},
options.output
), // Merge with env dependent settings
optimization: options.optimization,
node: {
fs: 'empty',
net: 'empty',
},
module: {
rules: [
{
test: /\.js$/, // Transform all .js files required somewhere with Babel
exclude: /node_modules\/(?!(react-redux-toastr)\/).*/,
use: {
loader: 'babel-loader',
options: options.babelQuery,
},
},
{
test: /\.(scss|css)$/,
use: [
{
loader:
options.mode === 'development'
? 'style-loader'
: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
options: {
sourceMap: process.env.NODE_ENV === 'development',
},
},
{
loader: 'postcss-loader',
options: {
sourceMap: process.env.NODE_ENV === 'development',
},
},
{
loader: 'sass-loader',
options: {
sourceMap: process.env.NODE_ENV === 'development',
},
},
],
},
{
test: /\.(eot|svg|ttf|woff|woff2|otf)$/,
exclude: /images/,
use: 'file-loader',
},
{
test: /\.(jpg|png|gif)$/,
use: [
{
loader: 'file-loader',
},
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
},
optipng: {
optimizationLevel: 7,
},
gifsicle: {
interlaced: false,
},
pngquant: {
quality: '65-90',
speed: 4,
},
},
},
],
},
{
test: /\.svg$/,
include: /sprite/,
use: 'svg-sprite-loader',
},
{
test: /\.svg$/,
use: 'url-loader',
exclude: /sprite/,
},
{
test: /\.html$/,
use: 'html-loader',
},
{
test: /\.(mp4|webm)$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
},
},
},
],
},
plugins: options.plugins.concat([
new webpack.ProvidePlugin({
// make fetch available
fetch: 'exports-loader?self.fetch!whatwg-fetch',
}),
// Always expose NODE_ENV to webpack, in order to use `process.env.NODE_ENV`
// inside your code for any environment checks; UglifyJS will automatically
// drop any unreachable code.
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
API_V: JSON.stringify(process.env.API_V),
CONTENT_PREVIEW: JSON.stringify(process.env.CONTENT_PREVIEW),
},
}),
]),
resolve: {
modules: ['app', 'node_modules'],
extensions: ['.js', '.jsx', '.react.js'],
mainFields: ['browser', 'main', 'jsnext:main'],
},
devtool: options.devtool,
target: 'web', // Make web variables accessible to webpack, e.g. window
performance: options.performance || {},
});
webpack.projd.babel.js:
// Important modules this config uses
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackPwaManifest = require('webpack-pwa-manifest');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const { HashedModuleIdsPlugin } = require('webpack');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = require('./webpack.base.babel')({
mode: 'production',
// In production, we skip all hot-reloading stuff
entry: [path.join(process.cwd(), 'app/app.js')],
// Utilize long-term caching by adding content hashes (not compilation hashes) to compiled assets
output: {
filename: '[name].[chunkhash].js',
chunkFilename: '[name].[chunkhash].chunk.js',
},
optimization: {
minimize: true,
nodeEnv: 'production',
sideEffects: true,
concatenateModules: true,
splitChunks: {
cacheGroups: {
styles: {
name: 'styles',
test: /\.(scss|css)$/,
chunks: 'all',
enforce: true,
},
},
},
runtimeChunk: true,
},
plugins: [
// Minify and optimize the index.html
new HtmlWebpackPlugin({
template: 'app/index.html',
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
inject: true,
}),
new WebpackPwaManifest({
name: 'LEDA',
short_name: 'LEDA',
description: '',
background_color: '#ffffff',
theme_color: '#00bae4',
icons: [
{
src: path.resolve('app/images/favicon.png'),
sizes: [72, 96, 120, 128, 144, 152, 167, 180, 192],
},
],
}),
new HashedModuleIdsPlugin({
hashFunction: 'sha256',
hashDigest: 'hex',
hashDigestLength: 20,
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
new UglifyJsPlugin({
parallel: true,
uglifyOptions: {
ecma: 6,
},
cache: path.join(__dirname, 'webpack-cache/uglify-cache'),
}),
],
performance: {
assetFilter: assetFilename =>
!/(\.map$)|(^(main\.|favicon\.))/.test(assetFilename),
},
});
webpack.dev.babel.js:
/**
* DEVELOPMENT WEBPACK CONFIGURATION
*/
const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CircularDependencyPlugin = require('circular-dependency-plugin');
const logger = require('../../server/logger');
const cheerio = require('cheerio');
const pkg = require(path.resolve(process.cwd(), 'package.json'));
const dllPlugin = pkg.dllPlugin;
const plugins = [
new webpack.ContextReplacementPlugin(
/\.\/locale$/,
'empty-module',
false,
/js$/
),
new webpack.HotModuleReplacementPlugin(), // Tell webpack we want hot reloading
new webpack.ContextReplacementPlugin(
/\.\/locale$/,
'empty-module',
false,
/js$/
),
new HtmlWebpackPlugin({
inject: true, // Inject all files that are generated by webpack, e.g. bundle.js
templateContent: templateContent(), // eslint-disable-line no-use-before-define
}),
new CircularDependencyPlugin({
exclude: /a\.js|node_modules|components\/Routes/, // exclude node_modules
failOnError: false, // show a warning when there is a circular dependency
}),
];
module.exports = require('./webpack.base.babel')({
mode: 'development',
// Add hot reloading in development
entry: [
'eventsource-polyfill', // Necessary for hot reloading with IE
'webpack-hot-middleware/client?reload=true',
path.join(process.cwd(), 'internals/dev-preamble.js'),
path.join(process.cwd(), 'app/app.js'), // Start with js/app.js
],
// Don't use hashes in dev mode for better performance
output: {
filename: '[name].js',
chunkFilename: '[name].chunk.js',
},
optimization: {
minimize: false,
},
// Add development plugins
plugins: dependencyHandlers().concat(plugins), // eslint-disable-line no-use-before-define
// Tell babel that we want to hot-reload
babelQuery: {
// require.resolve solves the issue of relative presets when dealing with
// locally linked packages. This is an issue with babel and webpack.
// See https://github.com/babel/babel-loader/issues/149 and
// https://github.com/webpack/webpack/issues/1866
presets: ['babel-preset-react-hmre'].map(require.resolve),
},
// Emit a source map for easier debugging
devtool: 'inline-source-map',
performance: {
hints: false,
},
});
/**
* Select which plugins to use to optimize the bundle's handling of
* third party dependencies.
*
* If there is a dllPlugin key on the project's package.json, the
* Webpack DLL Plugin will be used.
*
*/
function dependencyHandlers() {
// Don't do anything during the DLL Build step
if (process.env.BUILDING_DLL) {
return [];
}
// Don't do anything if package.json does not have a dllPlugin property
// Code splitting now included by default in Webpack 4
if (!dllPlugin) {
return [];
}
const dllPath = path.resolve(
process.cwd(),
dllPlugin.path || 'node_modules/react-boilerplate-dlls'
);
/**
* If DLLs aren't explicitly defined, we assume all production dependencies listed in package.json
* Reminder: You need to exclude any server side dependencies by listing them in dllConfig.exclude
*/
if (!dllPlugin.dlls) {
const manifestPath = path.resolve(dllPath, 'reactBoilerplateDeps.json');
if (!fs.existsSync(manifestPath)) {
logger.error(
'The DLL manifest is missing. Please run `npm run build:dll`'
);
process.exit(0);
}
return [
new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: require(manifestPath), // eslint-disable-line global-require
}),
];
}
// If DLLs are explicitly defined, we automatically create a DLLReferencePlugin for each of them.
const dllManifests = Object.keys(dllPlugin.dlls).map(name =>
path.join(dllPath, `/${name}.json`)
);
return dllManifests.map(manifestPath => {
if (!fs.existsSync(path)) {
if (!fs.existsSync(manifestPath)) {
logger.error(
`The following Webpack DLL manifest is missing: ${path.basename(
manifestPath
)}`
);
logger.error(`Expected to find it in ${dllPath}`);
logger.error('Please run: npm run build:dll');
process.exit(0);
}
}
return new webpack.DllReferencePlugin({
context: process.cwd(),
manifest: require(manifestPath), // eslint-disable-line global-require
});
});
}
/**
* We dynamically generate the HTML content in development so that the different
* DLL Javascript files are loaded in script tags and available to our application.
*/
function templateContent() {
const html = fs
.readFileSync(path.resolve(process.cwd(), 'app/index.html'))
.toString();
if (!dllPlugin) {
return html;
}
const doc = cheerio(html);
const body = doc.find('body');
const dllNames = !dllPlugin.dlls
? ['reactBoilerplateDeps']
: Object.keys(dllPlugin.dlls);
dllNames.forEach(dllName =>
body.append(`<script data-dll='true' src='/${dllName}.dll.js'></script>`)
);
return doc.toString();
}
Finally webpack.dll.babel.js:
/**
* WEBPACK DLL GENERATOR
*
* This profile is used to cache webpack's module
* contexts for external library and framework type
* dependencies which will usually not change often enough
* to warrant building them from scratch every time we use
* the webpack process.
*/
const { join } = require('path');
const defaults = require('lodash/defaultsDeep');
const webpack = require('webpack');
const pkg = require(join(process.cwd(), 'package.json'));
const dllPlugin = require('../config').dllPlugin;
if (!pkg.dllPlugin) {
process.exit(0);
}
const dllConfig = defaults(pkg.dllPlugin, dllPlugin.defaults);
const outputPath = join(process.cwd(), dllConfig.path);
module.exports = require('./webpack.base.babel')({
mode: 'development',
context: process.cwd(),
entry: dllConfig.dlls ? dllConfig.dlls : dllPlugin.entry(pkg),
optimization: {
minimize: false,
},
devtool: 'eval',
output: {
filename: '[name].dll.js',
path: outputPath,
library: '[name]',
},
plugins: [
new webpack.DllPlugin({
name: '[name]',
path: join(outputPath, '[name].json'),
}),
],
performance: {
hints: false,
},
});
package.json:
{
"name": "react-boilerplate",
"version": "3.4.0",
"description": "A highly scalable, offline-first foundation with the best DX and a focus on performance and best practices",
"repository": {
"type": "git",
"url": "git://github.com/react-boilerplate/react-boilerplate.git"
},
"engines": {
"npm": ">=3",
"node": ">=5"
},
"author": "Max Stoiber",
"license": "MIT",
"scripts": {
"analyze:clean": "rimraf stats.json",
"preanalyze": "npm run analyze:clean",
"analyze": "node ./internals/scripts/analyze.js",
"checkversion": "node ./internals/scripts/checkversion.js",
"preinstall": "npm run checkversion",
"postinstall": "npm run build:dll",
"prebuild": "npm run build:clean",
"build": "webpack --config internals/webpack/webpack.prod.babel.js --color --progress",
"build:prod": "cross-env NODE_ENV=production API_V=production npm run build",
"build:staging": "cross-env NODE_ENV=production API_V=staging npm run build",
"build:clean": "npm run test:clean",
"build:dll": "node ./internals/scripts/dependencies.js",
"start": "cross-env NODE_ENV=development node server",
"start:preview": "cross-env NODE_ENV=development CONTENT_PREVIEW=true node server",
"start:tunnel": "cross-env NODE_ENV=development ENABLE_TUNNEL=true node server",
"start:production": "npm run test && npm run build:prod && npm run start:prod",
"start:staging": "npm run test && npm run build:staging && npm run start:prod",
"start:prod": "cross-env NODE_ENV=production node server",
"presetup": "npm i chalk shelljs",
"setup": "node ./internals/scripts/setup.js",
"postsetup": "npm run build:dll",
"clean:all": "npm run analyze:clean && npm run test:clean && npm run build:clean",
"lint": "npm run lint:js",
"lint:eslint": "eslint",
"lint:js": "npm run lint:eslint -- . ",
"lint:fix": "npm run lint:eslint -- . --fix",
"lint:staged": "lint-staged",
"pretest:coverage": "npm run test:clean",
"test:clean": "rimraf ./coverage",
"test": "cross-env NODE_ENV=test jest",
"test:update": "cross-env NODE_ENV=test jest --updateSnapshot",
"test:coverage": "cross-env NODE_ENV=test jest --coverage",
"test:watch": "cross-env NODE_ENV=test jest --watch",
"coveralls": "cat ./coverage/lcov.info | coveralls",
"flow": "flow; test $? -eq 0 -o $? -eq 2"
},
"lint-staged": {
"*.js": "lint:eslint",
"*.{js,scss}": [
"prettier --write",
"git add"
]
},
"pre-commit": [
"lint:staged",
"test"
],
"dllPlugin": {
"path": "node_modules/react-boilerplate-dlls",
"exclude": [
"chalk",
"compression",
"cross-env",
"express",
"ip",
"minimist"
],
"include": [
"core-js",
"lodash",
"eventsource-polyfill"
]
},
"jest": {
"collectCoverageFrom": [
"app/**/*.{js,jsx}",
"!app/**/*.test.{js,jsx}",
"!app/containers/**/*.{js,jsx}",
"!app/*/RbGenerated*/*.{js,jsx}",
"!app/app.js",
"!app/routes.js"
],
"moduleDirectories": [
"node_modules",
"app"
],
"moduleNameMapper": {
".*\\.(css|less|styl|scss|sass)$": "<rootDir>/internals/mocks/cssModule.js",
".*\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/internals/mocks/image.js"
},
"setupTestFrameworkScriptFile": "<rootDir>/internals/testing/test-bundler.js",
"testRegex": "tests/.*\\.test\\.js$",
"setupFiles": [
"<rootDir>/internals/testing/test-setup.js"
]
},
"dependencies": {
"axios": "^0.15.3",
"babel-polyfill": "6.20.0",
"bluebird": "^3.5.0",
"chalk": "1.1.3",
"classnames": "^2.2.5",
"compression": "1.6.2",
"cross-env": "3.1.3",
"express": "4.14.0",
"fontfaceobserver": "2.0.7",
"history": "4.6.3",
"immutable": "3.8.2",
"ip": "1.1.4",
"leaflet": "^1.0.3",
"lodash": "4.17.2",
"marked": "^0.3.6",
"mime-types": "^2.1.16",
"minimist": "1.2.0",
"moment": "^2.18.1",
"moment-timezone": "^0.5.13",
"numeral": "^2.0.6",
"pace": "0.0.4",
"pace-js": "^1.0.2",
"prerender-node": "^2.7.2",
"qs": "^6.4.0",
"react": "15.4.1",
"react-dom": "15.4.1",
"react-foundation-components": "^0.12.0",
"react-helmet": "5.0.0",
"react-hot-loader": "^4.0.0",
"react-loadable": "^5.3.1",
"react-modal": "^1.7.7",
"react-player": "^1.5.0",
"react-progressbar.js": "^0.2.0",
"react-redux": "4.4.6",
"react-redux-toastr": "^7.0.0",
"react-router": "4.2.0",
"react-router-dom": "^4.2.2",
"react-router-redux": "5.0.0-alpha.6",
"react-router-scroll-memory": "^1.0.1",
"redux": "3.6.0",
"redux-immutable": "3.0.8",
"redux-saga": "0.16.0",
"redux-segment": "^1.6.2",
"request-promise": "^4.2.1",
"shortid": "^2.2.8",
"sitemap": "^1.13.0",
"store": "^2.0.4",
"tls": "0.0.1",
"tunnel-agent": "^0.6.0"
},
"devDependencies": {
"axios-mock-adapter": "^1.8.1",
"babel-cli": "6.18.0",
"babel-core": "6.21.0",
"babel-eslint": "7.1.1",
"babel-loader": "^7.1.4",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-dynamic-import-node": "1.0.0",
"babel-plugin-react-transform": "2.0.2",
"babel-plugin-root-import": "^5.1.0",
"babel-plugin-transform-es2015-modules-commonjs": "6.18.0",
"babel-plugin-transform-react-constant-elements": "6.9.1",
"babel-plugin-transform-react-inline-elements": "6.8.0",
"babel-plugin-transform-react-jsx-source": "^6.22.0",
"babel-plugin-transform-react-remove-prop-types": "0.2.11",
"babel-preset-env": "^1.6.1",
"babel-preset-latest": "6.16.0",
"babel-preset-react": "6.16.0",
"babel-preset-react-hmre": "1.1.1",
"babel-preset-stage-0": "6.16.0",
"cheerio": "0.22.0",
"circular-dependency-plugin": "^5.0.1",
"coveralls": "2.11.15",
"css-loader": "^0.28.11",
"empty-module": "0.0.2",
"enzyme": "2.6.0",
"eslint": "^3.19.0",
"eslint-config-airbnb": "^14.1.0",
"eslint-config-airbnb-base": "^11.1.3",
"eslint-config-prettier": "^2.6.0",
"eslint-import-resolver-webpack": "0.8.3",
"eslint-plugin-flowtype": "^2.30.4",
"eslint-plugin-import": "2.2.0",
"eslint-plugin-jsx-a11y": "^4.0.0",
"eslint-plugin-prettier": "^2.3.1",
"eslint-plugin-react": "7.5.1",
"eslint-plugin-redux-saga": "0.1.5",
"eventsource-polyfill": "0.9.6",
"exports-loader": "^0.7.0",
"file-loader": "^1.1.11",
"flow-bin": "^0.57.3",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"husky": "^0.14.3",
"image-webpack-loader": "^4.2.0",
"imports-loader": "^0.8.0",
"jest": "^22.4.3",
"jest-cli": "^22.4.3",
"lint-staged": "^3.2.1",
"mini-css-extract-plugin": "^0.4.0",
"ngrok": "2.2.4",
"node-plop": "0.5.4",
"node-sass": "^4.5.3",
"null-loader": "0.1.1",
"plop": "1.7.3",
"postcss-loader": "^2.1.3",
"pre-commit": "1.1.3",
"prettier": "^1.7.4",
"react-addons-test-utils": "15.4.1",
"redux-logger": "^2.10.2",
"rimraf": "2.5.4",
"sass-loader": "^6.0.7",
"shelljs": "0.7.5",
"sinon": "2.0.0-pre",
"style-loader": "^0.20.3",
"svg-sprite-loader": "^3.7.3",
"uglifyjs-webpack-plugin": "^1.2.4",
"url-loader": "^1.0.1",
"webpack": "^4.5.0",
"webpack-cli": "^2.0.14",
"webpack-dev-middleware": "^3.1.2",
"webpack-hot-middleware": "^2.22.0",
"webpack-pwa-manifest": "^3.6.2"
}
}
You need to install the plugin that is being asked:
npm install --save-dev babel-plugin-transform-es3-member-expression-literals
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"',
},
}),
you can try it.
Turns out the issue was to do with macos/windows back slashing and forward slashing differences, switching the exclude pattern to this:
exclude: /(node_modules|bower_components!react-redux-toastr)/
Fixed it.

Categories