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: '/',
},
},
};
Related
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",
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.
I am using Webpack to add support for ES6, react and some other things.
Right now I am getting error:
Refused to apply style from http://localhost:5500/bundle.css because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
So I checked sources tab in Google Chrome Developer Tools and the bundle.css doesn't even exist. What i am doing wrong ?
Here's my webpack config:
const path = require("path");
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./index.js",
output: {
path: path.resolve(__dirname, "/"),
publicPath: "/",
filename: "bundle.js"
},
mode: "development",
module: {
rules: [
{
test: /\.(js\jsx)$/,
exclude: /(node_modules|framework)/,
loader: require.resolve("babel-loader"),
options: { presets: ["#babel/preset-env"] }
},
{
test: /\.css$/,
use: [require.resolve("style-loader"), require.resolve("css-loader")]
},
{
test: /\.scss$/,
use: [
require.resolve("style-loader"),
require.resolve("css-loader"),
require.resolve("sass-loader")
]
}
]
},
resolve: { extensions: ["*", ".js", ".jsx"] },
devServer: {
port: 5500,
host: "<ip address>",
publicPath: "http://localhost:5500",
hotOnly: true
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "index.html"),
filename: "index.html",
inject: true
})
]
};
By default css is compiled into the js bundle during dev, to extract it out to a file for your prod build in webpack 4 use https://webpack.js.org/plugins/mini-css-extract-plugin/.
Older versions of webpack should use https://github.com/webpack-contrib/extract-text-webpack-plugin
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...
Today, after removing my node_modules and reinstalling them using npm install, my project doesn't seem to work.
Here's my webpack config
const webpack = require('webpack');
const path = require('path');
const srcPath = path.join(__dirname, './client');
const nodeEnv = process.env.NODE_ENV || 'development';
const isProd = nodeEnv === 'production';
module.exports = {
devtool: isProd ? 'hidden-source-map' : 'cheap-module-eval-source-map',
context: path.join(__dirname, './client'),
entry: {
js: './index.js',
vendor: ['react']
},
output: {
path: path.join(__dirname, './static'),
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.html$/,
loader: 'file',
query: {
name: '[name].[ext]'
}
},
{
test: /\.scss$/,
loaders: ['style', 'css', 'sass']
},
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loaders: ['babel-loader']
},
{
test: /\.(png|jpg|gif|otf|eot|svg|ttf|woff|woff2)/,
loader: 'url-loader'
},
{
test: /\.(txt|json)/,
loader: 'raw-loader'
}
],
},
resolve: {
extensions: ['', '.js', '.jsx'],
modules: [
path.resolve('./client'),
'node_modules'
],
alias: {
stores: `${srcPath}/stores/`,
components: `${srcPath}/components/`,
services: `${srcPath}/services`,
models: `${srcPath}/models`,
constants: `${srcPath}/constants`,
sources: `${srcPath}/sources`,
images: `${srcPath}/assets/images`,
appConstants: isProd ? `${srcPath}/constants/_prod` : `${srcPath}/constants/_dev`
}
},
plugins: [
new webpack.IgnorePlugin(/regenerator|nodent|js\-beautify/, /ajv/),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: Infinity,
filename: 'vendor.bundle.js'
}),
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: isProd
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: !isProd
},
output: {
comments: !isProd
},
sourceMap: !isProd
}),
new webpack.DefinePlugin({
'process.env': { NODE_ENV: JSON.stringify(nodeEnv) }
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.optimize.OccurrenceOrderPlugin()
],
devServer: {
contentBase: './client',
hot: true,
port: 3000,
historyApiFallback: true
}
};
My "client" folder with index.html and the rest of my code are in the same folder as webpack config.
Webpack does succesfully build, but going to localhost:3000, I get error message: "Cannot GET /"
Going to localhost:3000/client/index.html does serve my index.html, but my built files inserted using
<script src="./vendor.bundle.js"></script>
<script src="./bundle.js"></script>
doesn't load (GET to "http://localhost:3000/client/bundle.js" results in 404)
Anyone knows what's going on? I can't fix this issue, and I think I've tried everything, from changing path, publicPath to changing contentBase and moving my static files to different folder.
It's very strange, since this issue appeared only after reinstalling my project dependencies.
Every bit of help is much appreciated. Thanks.
There was an issue in webpack-dev-server#2.1.0-beta.3, which caused the contentBase option to be ignored. Could you try upgrading to 2.1.0-beta.4? It was just released.