Webpack 4 not outputting files after upgrade - javascript

I have been working on a legacy project for the past few days. I've been trying to update packages to modernize this project somewhat. This is an Electron application which I create an installer for after packaging so I need to get access to the outputted webpack bundle.
So after a lot of package upgrades I've managed to get the dev server running just fine and it hot reloads and all those nice things so that is great. I understand that bundle.js and the css files are loaded for memory in this case.
But the problem is when I'm trying to set the output folder for webpack and it's not being created or populated. Before these upgrades the folder would be created and populated with the outputs from webpack just fine, but this has stopped since upgrading to webpack 4.
I would really appreciate any pointers or help that one of you kind people to point out to me. Cheers!
Below are my relevant webpack config files:
webpack.config.production.js
import webpack from 'webpack';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
const baseConfig = require('./webpack.config.base');
const config = {
...baseConfig,
mode: 'production',
devtool: 'source-map',
entry: ['#babel/polyfill', './app/index'],
plugins: [
...baseConfig.plugins,
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
}),
new ExtractTextPlugin('style.css', { allChunks: true })
],
output: {
...baseConfig.output,
publicPath: '../dist/'
},
module: {
...baseConfig.module,
rules : [
...baseConfig.module.rules,
{
test: /\.global\.css$/,
loader: ExtractTextPlugin.extract(
'style-loader',
'css-loader'
)
},
{
test: /^((?!\.global).)*\.css$/,
loader: ExtractTextPlugin.extract(
'style-loader',
'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'
)
}
]
},
target: 'electron-renderer'
};
export default config;
webpack.config.base.js
import path from 'path';
import WebpackNotifierPlugin from 'webpack-notifier';
export default {
module: {
rules : [
{
test: /\.jsx?$/,
use: [
{
loader: 'babel-loader'
}
],
exclude: /node_modules/
}
]
},
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
libraryTarget: 'commonjs2'
},
resolve: {
extensions: ['.js', '.jsx', '.json'],
mainFields: ['webpack', 'browser', 'web', 'browserify', ['jam', 'main'], 'main']
},
plugins: [
new WebpackNotifierPlugin({excludeWarnings: true})
],
externals: [
]
};
Relevant packages
"#babel/core": "^7.1.6",
"webpack": "4.46.0",
"electron": "15.5.5",

Related

React library peer dependency conflict

I'm creating a small library to power a few of my projects.
I found that i was getting issues inside the client apps with multiple conflicting versions of react when importing my library. This led me to setting both react and react-dom under peer dependencies in the library package.json which fixed the problem.
However, I am trying to run a sandbox environment via a webpack bundler to test and play with components within the library repo as i am working on it (instead of using npm link), and now I am having an issue whereby react is no longer being detected as a local dependency.
Here is my webpack config.
FWIW, when building out the components for production use I am exporting modules via tsconfig, and not using webpack at all. But i'm finding it difficult to resolve this situation of maintaining a test environment :/
const path = require('path');
const webpack = require('webpack');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const isDevelopment = process.env.NODE_ENV !== 'production';
module.exports = {
mode: isDevelopment ? 'development' : 'production',
entry: path.resolve(__dirname, './sandbox/web/index.tsx'),
module: {
rules: [
{
test: /\.tsx?$/,
exclude: /node_modules/,
use: ['babel-loader', 'ts-loader'],
},
{
test: /\.(s(a|c)ss)$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.svg?$/,
loader: 'svg-url-loader',
options: {
limit: 10000,
},
},
],
},
resolve: {
extensions: ['.js', '.jsx', '.tsx', '.ts'],
alias: {
src: path.resolve(__dirname, 'src'),
components: path.resolve(__dirname, 'src/components'),
hooks: path.resolve(__dirname, 'src/hooks'),
themes: path.resolve(__dirname, 'src/themes'),
types: path.resolve(__dirname, 'src/types'),
utils: path.resolve(__dirname, 'src/utils'),
'react-native$': 'react-native-web',
},
},
output: {
path: path.resolve(__dirname, './sandbox/web'),
filename: 'bundle.js',
},
devtool: 'inline-source-map',
watchOptions: {
poll: true,
ignored: '/node_modules/',
},
plugins: [
new HtmlWebPackPlugin({
template: path.resolve(__dirname, './sandbox/web/index.html'),
filename: 'index.html',
}),
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/native$/,
contextRegExp: /src$/,
}),
],
devServer: {
historyApiFallback: {
index: '/',
},
},
};

Webpack file-loader and Svelte style background image not working [duplicate]

Trying to load a CSS background image, defined in SCSS, and serving via WebPack devServer.
The background image defined in SCSS is picked up by WebPack, but it doesn't show on the page.
I have tried setting publicPath option in MiniCssExtractPlugin.loader and looked at all the answers I could find related to this problem, but haven't been able to get this to work.
Update: Also tried setting publicPath option in file-loader. According to the documentation this defaults to the output publicPath, which is the same in my case.
Update: When using an absolute path in SCSS it compiles to CSS as that exact path, but that isn't going to work as local dev and staging and prod all have different paths.
Relevant part of the output when running webpack-dev-server:
Child mini-css-extract-plugin node_modules/css-loader/index.js??ref--5-1!node_modules/sass-loader/dist/cjs.js??ref--5-2!index.scss:
Asset Size Chunks Chunk Names
pages/index/404#2x.png 29.2 KiB [emitted]
index.scss:
body {
background: url("./pages/index/404#2x.png");
}
CSS output:
body {
background: url([object Module]);
}
My WebPack config:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');
const outputDir = 'dist/website';
const publicPath = '/web/website/';
module.exports = {
mode: 'development',
devtool: 'source-map',
entry: './index.ts',
output: {
path: path.resolve(__dirname, outputDir),
publicPath: publicPath,
filename: 'bundle.js',
},
resolve: {
extensions: ['.ts', '.js'],
},
module: {
rules: [
{
test: /\.ts$/,
use: ['ts-loader'],
},
{
test: /\.scss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: 'css-loader',
options: {
sourcemap: true,
},
},
{
loader: 'sass-loader',
options: {
sourceMap: true,
},
},
],
},
{
test: /\.(png|jpe?g|gif|svg|webp)$/i,
use: [
{
loader: 'file-loader',
options: {
name: '[path][name].[ext]',
},
},
],
},
],
},
plugins: [
new MiniCssExtractPlugin({
path: path.resolve(__dirname, outputDir),
filename: '[name].css',
chunkFilename: '[id].css',
}),
new CleanWebpackPlugin([outputDir]),
],
devServer: {
contentBase: path.join(__dirname, outputDir),
publicPath: publicPath,
port: 9009,
proxy: {
'/': 'http://127.0.0.1:5000/',
},
},
};
index.ts:
import './index.scss';
console.log('WebPack is working!');
I have figured out the issue: css-loader was on version 1.0.0. Probab ly because it was installed a long time ago.
Upgrading to the latest version of css-loader with npm install css-loader#latest --save-dev solved the issue.

react production build, assets not loading

I am experiencing annoying problem, when i run my react app in development environment it all works ok, but when i try to build to production, all the links are wrong.
assume this tree:
main_directory
public/
svg/
some_img.svg
src/
components/
some_component.jsx
App.js
index.js
Now in some_component.jsx i am referencing svg file in this way:
src="/public/svg/some_img.svg"
however after building to production this path is untouched and therefore cannot access file anymore, as there i would need it to be changed to this:
src="svg/some_img.svg"
i was playing in the webpack config file, i thought that maybe by setting:
publicPath: "/"
to:
publicPath: "/public/"
would resolve the problem but the only thing it did was error during application start:
CANNOT GET/
my webpack config:
const HtmlWebPackPlugin = require("html-webpack-plugin");
const htmlPlugin = new HtmlWebPackPlugin({
template: "./public/index.html",
filename: "./index.html"
});
module.exports = {
output: {
filename: "main.[hash:8].js",
publicPath: "/"
},
module: {
rules: [
{
test: /\.jsx$/,
exclude: /node_modules/,
loader: "babel-loader?presets[]=react"
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.(sass|scss)$/,
use: ["style-loader", "css-loader", "sass-loader", "postcss-loader"]
},
{
test: /\.svg$/,
loader: "svg-sprite-loader"
}
]
},
plugins: [htmlPlugin],
devServer: {
historyApiFallback: {
rewrites: [{ from: /^\/$/, to: "/index.html" }]
}
},
resolve: {
extensions: [".js", ".jsx", ".json"]
}
};
How does one resolve this problem, so for both dev and production paths are unified?
How about importing the svg and then referencing the imported variable:
import someImg from "../../public/svg/some_img.svg"
src={someImg}
this is the solve for the question, config required for to specify path:
module: {
...
rules: [
{
test: /\.(png|jpg|gif|svg|ico)$/,
loader: 'file-loader',
query:{
outputPath: './img/',
name: '[name].[ext]?[hash]'
}
}
...
]
}

Using html-webpack-plugin to generate an index.html file in Webpack (project using vue-simple boilerplate)

I'm trying to generate my own index.html file every time I build my application in Webpack and to do so, I installed html-webpack-plugin.
I understand that in order generate an index.html file in my dist folder, I need to have the following in my webpack.config.js file:
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name].js',
},
plugins: [
new HtmlWebpackPlugin(), // creates an index.html file
],
With the above settings, it should generate the following, which is my desired output:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Webpack App</title>
</head>
<body>
<script type="text/javascript" src="build.js"></script></body>
</html>
Unfortunately, I've been using the vue-simple Webpack boilerplate to build my VueJS learning project and as a result, it has a publicPath entry in the output section:
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: '[name].js',
}
With the above settings, the html-webpack-plugin understandably generates the following script tag in the index.html file in my dist folder which is NOT what I need since src is now pointing to "/dist/build.js".
<script type="text/javascript" src="/dist/build.js"></script></body>
If I remove publicPath from my output settings, I can't load my page from my development server since everything breaks. I read this SO post about publicPath but I'm still unsure of what I should do to achieve my goals since everything was set up by the boilerplate. How should I edit my webpack.config.js file in order to generate my desired index.html file when I build without breaking anything on my dev server?
Below is my full webpack.config settings:
const path = require('path');
const webpack = require('webpack');
require("babel-polyfill"); // for async await
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// babel-polyfill for async await
// entry: ["babel-polyfill", "./src/main.js"],
entry: {
build: ["babel-polyfill", "./src/main.js"]
},
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: '[name].js', // this will output as build.js
},
module: {
rules: [{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
}, {
test: /\.scss$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader'
],
}, {
test: /\.sass$/,
use: [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax'
],
}, {
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
// Since sass-loader (weirdly) has SCSS as its default parse mode, we map
// the "scss" and "sass" values for the lang attribute to the right configs here.
// other preprocessors should work out of the box, no loader config like this necessary.
'scss': [
'vue-style-loader',
'css-loader',
'sass-loader'
],
'sass': [
'vue-style-loader',
'css-loader',
'sass-loader?indentedSyntax'
]
}
// other vue-loader options go here
}
}, {
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
}, {
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
include: '/src/assets/images',
options: {
name: '[name].[ext]?[hash]'
}
}]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json']
},
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
performance: {
hints: false
},
plugins: [
new webpack.ProvidePlugin({ // this injects the following into .vue files
_: "lodash",
math: "mathjs",
moment: "moment",
axios: "axios",
Chart: "chart.js",
firebase: "firebase",
}),
new HtmlWebpackPlugin(), // creates an index.html file in dist
],
devtool: '#eval-source-map'
};
if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
]);
}
Below is the folder structure I have:
You can alternatively use vue-cli for scaffolding. (Read the vue documentation for vue-cli here https://vuejs.org/2015/12/28/vue-cli/)
The following will give you a full preconfigured webpack config :
vue init webpack project-name
Then you can use npm run build OR yarn build which will generate your index.html in the "dist" folder.

Optimize Webpack React Babel - Does it make sense to include only selected plugins for Babel?

This question has two parts:
1.
Is there anything I can do in webpack config file to make my .js file even more compressed? Currently it is 984 kB.
I noticed that adding following plugins, doesn't change anything.
Are they included properly?
plugins: [
'transform-react-remove-prop-types',
'transform-react-constant-elements',
'transform-react-inline-elements'
]
My production config file:
const webpack = require('webpack');
const path = require('path')
const nodeModulesPath = path.resolve(__dirname, 'node_modules');
module.exports = {
context: __dirname,
devtool: 'cheap-module-source-map',
entry: './js/app/index.js',
output: {
path: path.join(__dirname, '/dist/js'),
filename: 'app.js'
},
cache: false,
debug: false,
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify('production')
}
}),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.UglifyJsPlugin({
compressor: {
warnings: false
}
})
],
resolve: {
alias: {
components: path.resolve(__dirname, './js/components/'),
app: path.resolve(__dirname, './js/app/'),
Auth: path.resolve(__dirname, './js/features/Auth/'),
DataDisplay: path.resolve(__dirname, './js/features/DataDisplay/'),
Forms: path.resolve(__dirname, './js/features/Forms/'),
},
extensions: ['', '.js', '.jsx', '.es6', '.json'],
},
stats: {
colors: true,
reasons: true,
chunks: false
},
module: {
loaders: [{
test: /\.(jsx|js|es6)?$/,
loader: 'babel-loader',
exclude: [nodeModulesPath],
query: {
presets: ['react', 'es2015'],
plugins: ['transform-react-remove-prop-types',
'transform-react-constant-elements',
'transform-react-inline-elements'
]
}
}, {
test: /\.json$/,
loader: 'json-loader'
}]
}
}
Second question is regarding babel, currently I am using just following ES2015 preset:
{
"presets": ["react", "es2015"],
}
However during "Complete Introduction to React (feat. Redux and React Router)" on Frontend Masters, Brian Holt pointed out that this preset contains a lot of stuff which is not really needed. Does it make sense to include only plugins I know I used?
For example I know I haven't used transform-regenerator (which according to him is a specially big) or transform-es2015-classes. And if it makes sense what is the easiest way to configure babel, without installing all of them separately...

Categories