I have a problem with webpack in my react app. My project structure is like below:
- root
-- app
--- src
---- App.tsx
---- index.tsx
--- package.json
--- assets
---- styles
----- main.css
--- scripts
---- webpack
----- webpack.dev.js
--- public
---- index.html
Can someone tell me why, I've got a many of errors like below during webpack build?
ERROR in ./src/features/app/settings/AppSettingsDetailsPage.tsx 29:0-43
Module not found: Error: Can't resolve 'src/store/store' in 'C:\Users\some\Desktop\some\some\app\src\features\app\settings'
example of using import in AppSettingsDetailsPage
import { dispatch } from "src/store/store";
Here is full of my webpack configuration, It's my first journey with webpack :(
Thanks for any help!
webpack.common.js
const path = require('path');
const webpack = require('webpack');
module.exports = {
target: 'web',
entry: {
app: './src/index.ts',
},
output: {
clean: true,
path: path.resolve(__dirname, '../../dist'),
filename: '[name].[contenthash].js',
publicPath: 'dist/',
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.json', '.svg'],
symlinks: false,
},
module: {
rules: [
{
test: /\.html$/,
exclude: /index.html/,
use: [
{
loader: 'html-loader',
options: {
sources: false,
minimize: {
removeComments: false,
collapseWhitespace: false,
},
},
},
],
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
}
],
},
};
webpack.dev.js
'use strict';
const ESLintPlugin = require('eslint-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');
const { merge } = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = (env = {}) =>
merge(common, {
devtool: 'inline-source-map',
mode: 'development',
entry: "./src/index.tsx",
module: {
rules: [
{
test: /\.tsx?$/,
use: {
loader: 'babel-loader',
options: {
cacheDirectory: true,
cacheCompression: false,
},
},
exclude: /node_modules/,
},
],
},
plugins: [
new ESLintPlugin({
lintDirtyModulesOnly: true,
extensions: ['.ts', '.tsx'],
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
new HtmlWebpackPlugin({
filename: path.resolve(__dirname, '../../public/index.html'),
template: path.resolve(__dirname, '../../public/index.html'),
inject: false,
chunksSortMode: 'none'
})
],
});
Related
I've never used Webpack before and I'm working on a project that's just vanilla JS and HTML. I'm having an issue accessing the values I set in .env. Here's my config.
const path = require("path");
const dotenv = require('dotenv');
var webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const Dotenv = require('dotenv-webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = () => {
env = dotenv.config().parsed;
const envKeys = Object.keys(env).reduce((prev, next) => {
prev[`process.env.${next}`] = JSON.stringify(env[next]);
return prev;
}, {});
return {
entry: {
main: './src/index.js'
},
output: {
path: path.join(__dirname, '../build'),
filename: '[name].bundle.js'
},
mode: 'development',
devServer: {
contentBase: "./src/",
publicPath: "./src/",
compress: true,
port: 9000,
overlay: true,
disableHostCheck: true
},
devtool: 'inline-source-map',
resolve: {
alias: {
process: "process/browser"
}},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
{
test: /\.(png|svg|jpe?g|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/'
}
}
]
},
{
test: /\.html$/,
use: {
loader: 'html-loader',
options: {
//attributes: ['img:src', ':data-src'],
minimize: true
}
}
}
]
},
plugins: [
new webpack.ProvidePlugin({
process: 'process/browser',
}),
new Dotenv(),
new webpack.DefinePlugin(envKeys),
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html'
}),
]
}
};
As you can see, I'm using dotEnv, definePlugin, and even the dotEnv-webpack plugin. Unfortunately, none of these solutions seem to allow me to access process.env.originURL.
originURL=https://localhost:3000
I'm not importing or requiring anything in my javascript file, index.js. I'm assuming this should work, but the console tells me that process is undefined.
console.log(process.env.originURL);
How can I access process.env.originURL in my index.js?
It should work. Maybe you could try this version:
new Dotenv({ systemvars: true })
If it still doesn't work, please show your package.json, as well as you .env file (randomize the values of course). Is .env at the root of you app?
I'm using webpack 4.43.0.
How do I prevent codesplitting from happening in webpack? All these files are created - 0.bundle.js up to 11.bundle.js (alongside the expected bundle.js), when I run webpack. Here's my webpack config:
/* eslint-env node */
const path = require('path');
module.exports = {
entry: './media/js/src/main.jsx',
mode: process.env.WEBPACK_SERVE ? 'development' : 'production',
output: {
path: path.resolve(__dirname, 'media/js'),
filename: 'bundle.js'
},
resolve: {
extensions: ['*', '.js', '.jsx']
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
include: path.resolve(__dirname, 'media/js/src'),
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['#babel/preset-env', '#babel/preset-react']
}
}
}
]
}
};
You can use webpack's LimitChunkCountPlugin to limit the chunk count produced by code splitting:
In your webpack.config.js file:
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
})
],
...
};
You could also pass the --optimize-max-chunks option to the webpack command directly.
So, in your package.json file:
{
"scripts": {
"build": "webpack --optimize-max-chunks 1",
...
},
...
}
Now, when you run npm run build, webpack will build only one file (or "chunk").
// Full list of options: https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-build
build: {
scopeHoisting: true,
vueRouterMode: 'history', // available values: 'hash', 'history'
showProgress: true,
gzip: false,
analyze: false,
distDir: 'dist',
productName:'pos_host_ui',
minify:true,
// Options below are automatically set depending on the env, set them if you want to override
// extractCSS: false,
// https://quasar.dev/quasar-cli/cli-documentation/handling-webpack
extendWebpack (cfg) {
const webpack = require('webpack');
cfg.plugins.push(
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
})
);
cfg.module.rules.push({
resourceQuery: /blockType=i18n/,
type: 'javascript/auto',
use: [
{ loader: '#kazupon/vue-i18n-loader' },
{ loader: 'yaml-loader' },
]
});
}
I have a simple HMR setup for reloading typescript files and postcss files. And they work perfectly well and modules reload without a page refresh. But when I change my HTML files, the website doesn't reload on it's own and the HTML content is not being hot-reloaded in.
This is my webpack config file:
const { resolve } = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: resolve(__dirname, 'src/main.ts'),
output: {
path: resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.ts$/,
loader: 'awesome-typescript-loader',
exclude: /node_modules/,
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
{
loader: 'postcss-loader',
}
]
}
]
},
devtool: 'source-map',
mode: 'development',
plugins: [
new HtmlWebpackPlugin({
template: resolve(__dirname, './src/index.html'),
}),
new webpack.HotModuleReplacementPlugin(),
new CleanWebpackPlugin(resolve(__dirname, 'dist'))
],
devServer: {
contentBase: resolve(__dirname, 'dist'),
port: 9000,
hot: true,
open: true,
progress: true,
}
}
With webpack 5,this setting is work for me:
devServer: {
hot:true,
open:true,
watchFiles: ['src/**/*']
},
webpack-dev-server github issue #3881
Problem is that html-webpack-plugin doesn't react to change and doesn't trigger the hmr.
In order to achieve that you could try something like this:
const { resolve } = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
let devServer; // set below in devserver part
function reloadHtml() {
this.plugin('compilation',
thing => thing.plugin('html-webpack-plugin-after-emit', trigger));
const cache = {};
function trigger(data, callback) {
const orig = cache[data.outputName];
const html = data.html.source();
if (orig && orig !== html)
devServer.sockWrite(devServer.sockets, 'content-changed');
cache[data.outputName] = html;
callback();
}
}
module.exports = {
entry: resolve(__dirname, 'src/main.ts'),
output: {
path: resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.ts$/,
loader: 'awesome-typescript-loader',
exclude: /node_modules/,
},
{
test: /\.css$/,
exclude: /node_modules/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
importLoaders: 1,
},
},
{
loader: 'postcss-loader',
}
]
}
]
},
devtool: 'source-map',
mode: 'development',
plugins: [
reloadHtml,
new HtmlWebpackPlugin({
template: resolve(__dirname, './src/index.html'),
}),
new webpack.HotModuleReplacementPlugin(),
new CleanWebpackPlugin(resolve(__dirname, 'dist'))
],
devServer: {
before(app, server) {
devServer = server;
},
contentBase: resolve(__dirname, 'dist'),
port: 9000,
hot: true,
open: true,
progress: true,
}
}
If you get :
DeprecationWarning: Tapable.plugin is deprecated. Use new API on `.hooks` instead
You can change reloadHtml to this:
function reloadHtml() {
const cache = {}
const plugin = {name: 'CustomHtmlReloadPlugin'}
this.hooks.compilation.tap(plugin, compilation => {
compilation.hooks.htmlWebpackPluginAfterEmit.tap(plugin, data => {
const orig = cache[data.outputName]
const html = data.html.source()
if (orig && orig !== html) {
devServer.sockWrite(devServer.sockets, 'content-changed')
}
cache[data.outputName] = html
})
})
}
Not sure if this is the case, but if you only want to extend your current HMR config to do a browser reload when your outer html/view files changed, then you can do it with a few extra lines using chokidar.
Maybe you already have it, because webpack-dev-server is using chokidar internally, but if not found then install it first with npm or yarn:
npm install chokidar --save
yarn add -D chokidar
Then require it in your webpack config:
const chokidar = require('chokidar');
Then in your devServer config:
devServer: {
before(app, server) {
chokidar.watch([
'./src/views/**/*.html'
]).on('all', function() {
server.sockWrite(server.sockets, 'content-changed');
})
},
Also check the API for more options.
I'm using it with Webpack4. Don't know if it works with earlier versions...
Hope it helps you or others looking for this situation.
I had a different thread here: React Build Tool and Dev Server
to setup React with Webpack. Seems like it is working but I have an issue with having the html page show the code from entry point app.js . I can see the code is in bundle.js. If I modify anything in app.js till the render method e.g enter a typo or something I see an error on console but nothing happens with the render() method. Not matter what I do there is no error and nothing shows but a blank page.
app.js
import React from 'react';
import ReactDOM from 'react-dom';
export default class App extends React.Component {
render() {
return (
ReactDOM.render(<h1>Render me!</h1>,
document.getElementById('app'))
);
}
}
Index.html
<!DOCTYPE html>
<html>
<head>
<!-- Bootstrap, latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css">
</head>
<body>
<div id="app"></div>
<script type="text/javascript" src='bundle.js'></script>
</body>
</html>
So if I view page source it just shows just
and not the expected Render me!
And just in case below is my webpack.config
var webpack = require('webpack');
var path = require('path');
module.exports = {
entry: {
bundle: './src/app.js'
},
output: {
path: path.join(__dirname, '/dist'),
filename: 'bundle.js'
},
module: {
loaders: [{
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['react', 'es2015', 'stage-1']
}
}]
},
resolve: {
extensions: ['*', '.js', '.jsx']
}
};
Also this is from my package.json. I believe my bundle.js is being served from memory right now.
"scripts": {
"start": "webpack-dev-server --port 3000 --hot --inline",
"build": "webpack --progress --colors"
}
I run npm start to compile and start the server. I was expecting npm build will build to dist folder but it doesn't . For now I just want this working one way or the other so I can start coding.
And .babelrc
{
"presets":[
"es2017", "react"
]
}
You are using WebPack 3.x?
Try this config:
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const PreloadWebpackPlugin = require('preload-webpack-plugin');
const autoprefixer = require('autoprefixer');
const staticSourcePath = path.join(__dirname, 'static');
const sourcePath = path.join(__dirname);
const buildPath = path.join(__dirname, 'dist');
module.exports = {
devtool: 'source-map',
devServer: {
historyApiFallback: true,
contentBase: './'
},
entry: {
"index" :path.resolve(sourcePath, 'index.js')
},
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].[chunkhash].js',
publicPath: '/'
},
resolve: {
extensions: ['.webpack-loader.js', '.web-loader.js', '.loader.js', '.js', '.jsx'],
modules: [
sourcePath,
path.resolve(__dirname, 'node_modules')
]
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('development')
}),
new webpack.optimize.ModuleConcatenationPlugin(),
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
filename: 'vendor.[chunkhash].js',
minChunks: Infinity
}),
new webpack.LoaderOptionsPlugin({
options: {
postcss: [
autoprefixer({
browsers: [
'last 3 version',
'ie >= 10'
]
})
],
context: staticSourcePath
}
}),
new webpack.HashedModuleIdsPlugin(),
new HtmlWebpackPlugin({
template: path.join(__dirname, 'index.html'),
path: buildPath,
excludeChunks: ['base'],
filename: 'index.html',
minify: {
collapseWhitespace: true,
collapseInlineTagWhitespace: true,
removeComments: true,
removeRedundantAttributes: true
}
}),
new PreloadWebpackPlugin({
rel: 'preload',
as: 'script',
include: 'all',
fileBlacklist: [/\.(css|map)$/, /base?.+/]
}),
new webpack.NoEmitOnErrorsPlugin()
],
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['env', 'react'],
}
},
include: sourcePath
},
{
test: /\.css$/,
exclude: /node_modules/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{ loader: 'css-loader', options: { minimize: true } },
'postcss-loader',
'sass-loader'
]
})
},
{
test: /\.(eot?.+|svg?.+|ttf?.+|otf?.+|woff?.+|woff2?.+)$/,
use: 'file-loader?name=assets/[name]-[hash].[ext]'
},
{
test: /\.(png|gif|jpg|svg)$/,
use: [
'url-loader?limit=20480&name=assets/[name]-[hash].[ext]'
],
include: staticSourcePath
}
]
}
};
I am working on an Angular project and use Webpack bundler. Everything was working fine until Webpack started to ignore my changes to Typescript files. When I change a Typescript file, Webpack first says:
[WDS] App updated. Recompiling...
followed by:
[WDS] Nothing changed.
Also, killing webpack-dev-server and rebuilding the sources doesn't make any difference. The changes I make to TS files are not applied in any way.
EDIT: Loader setup on request (which is exactly the same as in the Angular Developer Guide):
webpack.common.js:
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var helpers = require('./helpers');
module.exports = {
entry: {
'polyfills': './src/polyfills.ts',
'vendor': './src/vendor.ts',
'app': './src/main.ts'
},
resolve: {
extensions: ['', '.js', '.ts']
},
module: {
loaders: [
{
test: /\.ts$/,
loaders: ['awesome-typescript-loader', 'angular2-template-loader']
},
{
test: /\.html$/,
loader: 'html'
},
{
test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
loader: 'file?name=assets/[name].[hash].[ext]'
},
{
test: /\.css$/,
exclude: helpers.root('src', 'app'),
loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
},
{
test: /\.css$/,
include: helpers.root('src', 'app'),
loader: 'raw'
}
]
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: ['app', 'vendor', 'polyfills']
}),
new HtmlWebpackPlugin({
template: 'src/index.html'
})
]
};
webpack.dev.js:
var webpackMerge = require('webpack-merge');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var commonConfig = require('./webpack.common.js');
var helpers = require('./helpers');
module.exports = webpackMerge(commonConfig, {
devtool: 'cheap-module-eval-source-map',
output: {
path: helpers.root('dist'),
publicPath: 'http://localhost:8080/',
filename: '[name].js',
chunkFilename: '[id].chunk.js'
},
plugins: [
new ExtractTextPlugin('[name].css')
],
devServer: {
historyApiFallback: true,
stats: 'minimal'
}
});