I have been trying to setup webpack and react with typescript without the CRA jargon. The dev server doesn't emit the files to the index.html file to be viewed in the browser. The CRA template on eject has multiple js scripts for building and development mode but I want to omit that and keep the structure as clean and simple as possible
Package.json-
"scripts": {
"start": "webpack-dev-server --mode development --open --hot",
"build": "webpack --mode production"
}
The webpack config-
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin')
const CompressionPlugin = require('compression-webpack-plugin')
const HtmlWebpackChangeAssetsExtensionPlugin = require('html-webpack-change-assets-extension-plugin')
module.exports = {
entry: {
app: path.resolve(__dirname, 'src/index.tsx')
},
output: {
path: path.resolve(__dirname, 'dist'),
chunkFilename: '[name].[hash].chunk.js',
publicPath: '/codestage'
},
devtool: 'source-map',
resolve: {
extensions: ['.ts', '.tsx', '.js']
},
module: {
strictExportPresence: true,
rules: [
{
test: /\.js$/,
loader: require.resolve('babel-loader'),
exclude: /node_modules/,
options: {
compact: true
}
},
{
test: /\.tsx?$/,
include: path.join(__dirname, 'src'),
exclude: /node_modules/,
use: [
{ loader: 'babel-loader' },
{
loader: 'ts-loader',
options: {
transpileOnly: true
}
}
]
},
{ enforce: 'pre', test: /\.js$/, loader: 'source-map-loader' }
]
},
plugins: [
new HtmlWebpackPlugin({
template: './index.html',
jsExtension: '.gz',
filename: './index.html'
}),
new CompressionPlugin({
test: /\.js(\?.*)?$/i,
deleteOriginalAssets: true
}),
new ForkTsCheckerWebpackPlugin({ eslint: true }),
new HtmlWebpackChangeAssetsExtensionPlugin()
],
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
vendor: {
reuseExistingChunk: true,
test: /[\\/]node_modules[\\/]/,
name: 'vendor',
chunks: 'initial'
}
}
}
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React App</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
The directory structure-
Html inspect in browser-
How to solve this?
Actually,dev server is a tool to develop and debug.Everything is built in memory.You can try npm run build script to emit files that can be used to deploy.
Related
in my react app i'm using webpack 4,before implementing split chunk everything is working fine but after splitChunks it generating vendor.js file and it showing on html file also but page is blank.
my webpack file
const webpack = require('webpack');
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const CompressionPlugin = require('compression-webpack-plugin');
const VENDOR_LIBS =[
'antd','axios','moment','rc-time-picker','react',
'react-dom','react-ga','react-google-maps','react-loadable',
'react-redux','react-router','react-router-dom','recompose','redux','redux-thunk'
];
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
entry:{
vendor: VENDOR_LIBS,
main: './src/app.js',
},
output: {
path: path.join(__dirname, 'public'),
filename: '[name].chunkhash.bundle.js',
chunkFilename: '[name].chunkhash.bundle.js',
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.s?css$/,
use: ['style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
},{
test: /\.(gif|svg|jpg|png|ttf|eot|woff(2)?)(\?[a-z0-9=&.]+)?$/,
loader: "file-loader",
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'style.[contenthash].css',
}),
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: './src/index.html',
filename: 'index.html'
}),
new WebpackMd5Hash(),
new CompressionPlugin({
algorithm: 'gzip',
test : /\.js$|\.css$|\.eot?.+$|\.ttf?.+$|\.woff?.+$|\.svg?.+$/,
threshold: 10240,
minRatio: 0.8
}),
],
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: 'initial',
name: 'vendor',
test: 'vendor',
enforce: true
},
}
},
runtimeChunk: true,
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: true
}),
new OptimizeCSSAssetsPlugin({})
],
},
};
and in my /src/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500">
<link rel="stylesheet" href="<%=htmlWebpackPlugin.files.chunks.main.css %>">
<title>Book Ambulance - Stanplus</title>
</head>
<body>
<div id="app">
</div>
<script src="<%= htmlWebpackPlugin.files.chunks.main.entry %>"></script>
<script src="<%= htmlWebpackPlugin.files.chunks.vendor.entry %>"></script>
</body>
</html>
you can that those files are loading in browser but page is blank
i have to questions
a) why my app not showing nothing even not any error(may be something in output,splitChunks or in html page).
b) after doing UglifyJsPlugin,CompressionPlugin and dynamically adding routes and import libs/files but also my vendor.js file size is 580 KB,except all these techniques how can i reduce the size of my vendor.js file
i developed react app,before that i built same app on webpack v3 now i upgrade to v4.on v3 dev-server it worked fine but on v4 it is taking lot of time to build and every time its building whole project again(may be that's why)
my webpack.dev.js
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: './src/app.js',
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js'
},
devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.s?css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: true,
minimize:false,
importLoaders: 1,
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
},{
test: /\.(gif|svg|jpg|png|ttf|eot|woff(2)?)(\?[a-z0-9=&.]+)?$/,
loader: "file-loader",
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'styles.css',
}),
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html'
}),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('development')
}
})
],
devServer: {
contentBase: path.join(__dirname, 'public'),
historyApiFallback: true,
host:'0.0.0.0',
disableHostCheck: true,
}
};
and my scripts in package.json
"scripts": {
"start": "node server/server.js",
"build": "webpack --mode production --config=webpack.prod.js",
"dev": "webpack --mode development --config=webpack.dev.js",
"dev-server": "webpack-dev-server --config=webpack.dev.js"
}
it showing me error
ou are currently using minified code outside of NODE_ENV === 'production'. This means that you are running a slower development build of Redux. You can use loose-envify (https://github.com/zertosh/loose-envify) for browserify or DefinePlugin for webpack (http://stackoverflow.com/questions/30030031) to ensure you have the correct code for your production build.
but if console my process.env.NODE_ENV varialbe it showing me developement
i have two problems with dev-server on development mode
1) how can i reduce time of rebuilding on dev-server
2)on development mode also why it showing me production error.
Your development server is being run in production mode because you haven't set the --mode development argument in your dev-server NPM script. It seems like it isn't required since webpack-dev-server is, after all, a development server, but the argument is still necessary.
"dev-server": "webpack-dev-server --mode development --config webpack.dev.js"
To speed up the build in development, inject all CSS into the HTML with style-loader instead of extracting the CSS to a separate file. See the following code where I removed mini-css-extract-plugin and its loader.
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/app.js',
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js'
},
devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
},
{
test: /\.s?css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true,
minimize:false,
importLoaders: 1,
}
},
{
loader: 'sass-loader',
options: {
sourceMap: true
}
}
]
},
{
test: /\.(gif|svg|jpg|png|ttf|eot|woff(2)?)(\?[a-z0-9=&.]+)?$/,
loader: 'file-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html'
})
],
devServer: {
contentBase: path.join(__dirname, 'public'),
historyApiFallback: true,
host:'0.0.0.0',
disableHostCheck: true,
}
};
Building source maps will slow the build down as well, so consider if you truly need them.
The answer is: you are using the inline-source-map devtool which causes the build & rebuild process super slow.
According to the Official Webpack Document, they said:
Choose a style of source mapping to enhance the debugging process. These values can affect build and rebuild speed dramatically.
For more information, you could read it here: https://webpack.js.org/configuration/devtool/#devtool
Hopefully, that helps!
Adding caching to babel-loader can shave off some time:
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: true,
cacheCompression: false
}
}
]
}
https://github.com/babel/babel-loader#options
I have had the same issue and i completely remove source map for development and now is super-fast.My webpack.common.js file looks like this
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const path = require('path');
module.exports = {
entry: './src/app.js',
output: {
filename: '[name].[hash].js',
path: path.resolve('./dist')
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: [{
loader: 'babel-loader'
},
{
loader: 'eslint-loader'
}]
}, {
test: /\.s?css$/,
use: [
{
loader: 'css-loader',
options: {
sourceMap: false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: false
}
}
]
}]
},
optimization: {
minimize: true
},
plugins: [
new HtmlWebPackPlugin({
template: 'index.html'
}),
new CleanWebpackPlugin()
]
};
and my webpack.dev.js looks like this one
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development',
devServer: {
host: 'localhost',
disableHostCheck: true,
port: 3000,
open: true,
historyApiFallback: true
}
});
With this aproach we losing source-map in development and get fast at speed,if you really need source-mapping in dev-mode choose some light-weight source-map like cheap-eval-source-map and change it when you go in production build to inline-source-map because inline-source-map decreases dramatically size of main.js || bundle.js file.
bundle.js works on localhost:3000/abc (because it looks in the localhost:3000/assets folder), but if I go to localhost:3000/abc/xyz I get a 404 (because it looks in the localhost:3000/abc/assets folder).
My webpack.config.js
var webpack = require("webpack");
var path = require('path')
module.exports = {
entry: "./src/index.js",
output: {
path: path.join(__dirname, '/dist'),
filename: "bundle.js",
publicPath: "/assets/",
},
devServer: {
inline: true,
contentBase: "./dist",
port: 3000,
historyApiFallback: true,
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
loader: "babel-loader",
query: {
presets: ["#babel/preset-env", "#babel/preset-react"]
}
},
{
type: 'javascript/auto',
test: /\.html/,
exclude: /(node_modules)/,
},
{
test: /\.css$/,
use:['style-loader','css-loader']
},
{
test: /\.scss$/,
use:['style-loader','css-loader', 'sass-loader']
}
]
}
}
I cannot use an absolute path for the publicPath.
How can I access bundle.js when I am multiple layers deep?
In the index.html I had
<script type="text/javascript" src="./assets/bundle.js"></script>
All I had to do is to change it to
<script type="text/javascript" src="/assets/bundle.js"></script>
I am trying to run a simple electron app with webpack and react.
So I set my webpack with target: "electron"
const webpack = require('webpack');
const path = require('path');
const SassLintPlugin = require('sasslint-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const extractSass = new ExtractTextPlugin({
filename: '[name].css',
disable: process.env.NODE_ENV === 'development',
});
module.exports = {
target: 'electron',
context: path.resolve(__dirname),
entry: {
app: './assets/js/components/index',
main: './main',
},
output: {
publicPath: '/dist/',
path: path.resolve('./dist/'),
filename: '[name].js',
},
module: {
rules: [
{
test: /\.jsx?$/,
loader: 'eslint-loader',
include: path.resolve(__dirname, './assets/js/'),
exclude: /node_modules/,
enforce: 'pre',
},
{
test: /\.jsx?$/,
include: path.resolve(__dirname, './assets/js/'),
exclude: /node_modules/,
loader: 'babel-loader',
},
{
test: /\.scss$/,
include: path.resolve(__dirname, './assets/scss/'),
loader: extractSass.extract({
use: [
{ loader: 'css-loader' },
{ loader: 'sass-loader' },
],
// use style-loader in development
fallback: 'style-loader',
}),
exclude: /node_modules/,
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
loader: 'file?name=public/fonts/[name].[ext]',
},
],
},
resolve: {
extensions: ['.js', '.jsx'],
modules: [path.resolve(__dirname, 'node_modules')],
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
names: ['main'],
}),
new SassLintPlugin({
configFile: '.sass-lint.yml',
context: [path.resolve(__dirname, './assets/scss/')],
ignoreFiles: [],
ignorePlugins: [],
glob: '**/*.s?(a|c)ss',
quiet: false,
failOnWarning: false,
failOnError: true,
testing: false,
}),
extractSass,
new HtmlWebpackPlugin({
title: 'Calendar Component',
template: 'assets/index-template.html',
minify: {
collapseWhitespace: process.env.NODE_ENV === 'production',
},
}),
],
};
My bundles are created correctly into index.html, app.js and main.js and ./dist folder.
But I got an error: Unable to find Electron at my_path_project/dist
My scripts at package.json are:
"main": "./dist/main.js",
"scripts": {
"start": "electron ./dist/",
"dev": "NODE_ENV=development webpack"
},
Can anyone help me?
Thanks in advance.
Probably because there is no one. You are install electron to your node modules, you are referring to that in modules: [path.resolve(__dirname, 'node_modules')].
Simply change your start command to:
"main": "dist/main.js",
"scripts": {
"start": "electron ."
},
The solution from #Anatoly helped me to appear the electron windows, but I couldn't run react over electron.
So I found this tutorial that worked to run react over electron:
https://medium.freecodecamp.com/building-an-electron-application-with-create-react-app-97945861647c
I hope this will help ;)
I am new to es6/react js and webpack and from last 6 days I am trying to create startkit for react app with es6 and webpack below is my webpack.config.js , I am successfully able to configure web pack dev server. My app is running on http:/localhost:8080/webpack-dev-server. When I am running npm build to generate bundle.js. if I am running my app only using localhost:8080 my app is running in chrome but giving error in mozilla (r.render is not function). Webpack is very confusing... Can we run file bundle.js file locally on file:// server. means like in normal html file if I include that bundle.js file it should work right?
My webpack.config.js
var path = require('path');
var webpack = require('webpack');
//var commonsPlugin = new webpack.optimize.CommonsChunkPlugin('common.js');
var mainPath = path.join(__dirname, 'app', 'index.js');
var buildPath = path.join(__dirname, 'dist/assets/');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var autoprefixer = require('autoprefixer')
var sassLoaders = [
'css-loader?sourceMap',
'postcss-loader',
'sass-loader?sourceMap&includePaths[]=' + path.join(__dirname, './app')
]
module.exports = {
// Makes sure errors in console map to the correct file
// and line number
devtool: 'cheap-module-source-map',
entry: {
'vendor': ['react','react-dom'],
"bundle":mainPath
},
module: {
loaders: [
{
test: [/\.js$/],
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
},
// //{ test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // use ! to chain loaders
// { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // use ! to chain loaders
// { test: /\.s?css$/, loaders: ['style', 'css', 'sass','css?sourceMap', 'sass?sourceMap'] }
{ test: /\.scss$/,
loader: ExtractTextPlugin.extract('style-loader', sassLoaders.join('!'))
},
{ test: /\.(ttf|otf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/, loader: 'file-loader?name=/fonts/[name].[ext]' }
]
},
output: {
// We need to give Webpack a path. It does not actually need it,
// because files are kept in memory in webpack-dev-server, but an
// error will occur if nothing is specified. We use the buildPath
// as that points to where the files will eventually be bundled
// in production
path: buildPath,
filename: '[name].js',
publicPath: 'http://localhost:8080/assets'
},
plugins: [
// Pro-tip: Order matters here.
new ExtractTextPlugin('[name].css'), new webpack.optimize.CommonsChunkPlugin(['bundle', 'vendor'], '[name].js')
],
postcss: [
autoprefixer({
browsers: ['last 2 versions'],
//path: "./dist",
filename: '[name].js',
// Everything related to Webpack should go through a build path,
// localhost:8080/build. That makes proxying easier to handle
publicPath: '/dist/'
})
],
resolve: {
extensions: ['', '.js', '.jsx','.sass','.woff','.ttf','.eot','.svg'],
root: [path.join(__dirname, './app')]
},
watch:true
};
my index.html
<!DOCTYPE html>
<html>
<head>
<title>React Home Page</title>
<link rel="stylesheet" href="assets/bundle.css" />
</head>
<body>
<div id="react-app"></div>
<script type="text/javascript" src="assets/vendor.js"></script>
<script type="text/javascript" src="assets/bundle.js"></script>
</body>
</html>
You don't have to link it yourself, webpack does that for you.
the HtmlWebpackPlugin will make sure that the bundle is being linked in the file that you configure.
var path = require("path");
var HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
entry: "./app/index.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "index_bundle.js"
},
module: {
rules: [
{ test: /\.(js)$/, use: "babel-loader" },
{ test: /\.css$/, use: ["style-loader", "css-loader"] }
]
},
plugins: [
new HtmlWebpackPlugin({
template: "app/index.html"
})
]
};