When I build my js bundle with webpack using webpack-dev-server my code runs twice every time. Not sure how to fix it.
Screenshot of Developer Tools console
My webpack config:
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
devtool: 'cheap-eval-sourcemap',
entry: [
'webpack-dev-server/client?http://localhost:8080',
'webpack/hot/dev-server',
path.join(__dirname, '../src/main')
],
output: {
path: path.join(__dirname, '../dist'),
filename: 'bundle.js'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new HtmlWebpackPlugin({
template: path.join(__dirname, '../src/index.html')
}),
new CopyWebpackPlugin([
{
from: path.join(__dirname, '../assets'),
to: path.join(__dirname, '../dist/assets')
}
])
],
devServer: {
contentBase: path.join(__dirname, '../dist'),
outputPath: '/lol',
hot: true
},
module: {
loaders: [
{
test: /\.js$/,
loaders: ['babel-loader'],
include: path.join(__dirname, '../src')
}
]
}
};
in the template file you might have manually added a loading the bundle.
If you don't have the
inject: false
option in
new HtmlWebpackPlugin({
template: path.join(__dirname, '../src/index.html')
}),
the bundle will get added again.
Expanding a bit on #Emil Perhinschi's and #ggloren's earlier replies ...
Alternatively, if your ../src/index.html file does not rely on any script other than <script src="bundle.js"></script>, simply remove the latter from your index.html.
Per https://github.com/jantimon/html-webpack-plugin, the default for inject is true and ...
When passing true or 'body' all javascript resources will be
placed at the bottom of the body element.
Thus your two instantiations of bundle.js are:
The <script src="bundle.js"></script> that you (presumably) coded, and
HtmlWebpackPlugin's injection "at the bottom of the body element".
Related
I'm writing a react app and everything works fine when I navigate to localhost:3000, but when I try to go to localhost:3000/foo/page, I get an error message that tells me localhost:3000/foo/bundle.js cannot be loaded.
To me, this looks like a problem with Webpack looking in the wrong place for bundle.js, but I'm not sure. How do I get the app to always look at localhost:3000 for bundle.js?
This is some of my webpack config.
var TARGET = process.env.npm_lifecycle_event;
var ROOT_PATH = path.resolve(__dirname);
var APP_PATH = path.resolve(ROOT_PATH, 'app');
var BUILD_PATH = path.resolve(ROOT_PATH, 'dist');
process.env.BABEL_ENV = TARGET;
var common = {
entry: APP_PATH,
output: {
path: BUILD_PATH,
filename: 'bundle.js'
},
module: {
loaders: [
{
test: /\.jsx?$/,
loaders: ['babel'],
include: APP_PATH
},
{
test: /\.svg$/,
loader: 'url-loader?limit=8192',
include: APP_PATH
},
{
test: /\.png$/,
loader: 'url-loader?limit=8192',
include: APP_PATH
},
{
test: /\.ico$/,
loader: 'url-loader?limit=8192',
include: APP_PATH
}
]
},
plugins: [
new HtmlWebpackPlugin({
title: 'foobar',
template: path.resolve(APP_PATH, 'index.html'),
favicon: path.resolve(APP_PATH, 'images', 'favicon.ico')
})
]
};
if (TARGET === 'start' || !TARGET) {
module.exports = merge(common, {
devtool: 'eval-source-map',
module: {
loaders: [
{
test: /\.scss$/,
loaders: ['style', 'css', 'sass'],
include: APP_PATH
}
]
},
devServer: {
historyApiFallback: true,
hot: true,
inline: true,
port: 3000,
progress: true
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
});
}
Add output.publicPath: '/' to your webpack config.
output: {
path: BUILD_PATH,
publicPath: '/',
filename: 'bundle.js'
}
HtmlWebpackPlugin most probably generates the file which have:
<script src="bundle.js"></script>
Setting up output.publicPath: '/' will make it:
<script src="/bundle.js"></script>
From Webpack Config page:
output.publicPath
The publicPath specifies the public URL address of
the output files when referenced in a browser. For loaders that embed
or tags or reference assets like images, publicPath is
used as the href or url() to the file when it’s different then their
location on disk (as specified by path). This can be helpful when you
want to host some or all output files on a different domain or on a
CDN. The Webpack Dev Server also takes a hint from publicPath using it
to determine where to serve the output files from. As with path you
can use the [hash] substitution for a better caching profile.
Lost another day by figuring out how to set up webpack-dev-server with hot reload. I would like to serve my JS and CSS assets in index.html with following paths: /dist/js/app.min.js and /dist/css/styles.min.css.
How the hell I am suppose to configurate webpack.config.js to load my assests in index.html with correct paths mentioned above? With current configuration webpack-dev-server is holding my build inside /dist folder only and in index.html I have to set paths without js or css folder, e.g.: (<script src="/dist/app.min.js" />).
My webpack.config.js:
const path = require('path');
const webpack = require('webpack');
module.exports = {
context: path.resolve(__dirname, './'),
entry: './src/app.js',
output: {
publicPath: '/dist/',
path: path.join(__dirname, '/dist/js'),
filename: 'app.min.js'
},
devServer: {
hot: true
},
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx']
},
module: {
rules: [
{
test: /\.(scss|sass|css)$/,
use: ['style-loader', 'css-loader', 'sass-loader']
}
]
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin()
]
};
My project structure:
Are you familiar with the HtmlWebpackPlugin? https://webpack.js.org/plugins/html-webpack-plugin/#src/components/Sidebar/Sidebar.jsx
This is my setup:
new HtmlWebpackPlugin({
template: project.paths.client('index.html'), // absolute url to index.html
hash: false,
filename: 'index.html',
inject: 'body',
})
This will take your entry(ies) and inject them into your index.html
Actually, I wrote webpack for my website which was using the reactjs. In that I have lot of images and scss files so, that it is taking more amount of time to create bundle.js file upto that the website was in loading state. So, how I can increase the execution speed.
webpack.config.js
const path = require("path");
const webpack = require("webpack");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
let config = {
entry: ["babel-polyfill", "./app/js/index.js"],
output: {
path: path.resolve(__dirname, "public"),
filename: "./build.js",
//publicPath: "/"
},
resolve: {
alias: {
"js": path.resolve(__dirname, "app/js"),
"css": path.resolve(__dirname, "app/css")
},
extensions: [".js", ".jsx"]
},
module: {
rules: [
{test: /\.(js|jsx)$/, loader: "babel-loader"},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
loader: 'url-loader'
},
{test: /\.scss$/, loader: ExtractTextPlugin.extract(["css-loader", "sass-loader"])},
{test: /\.(jpg|gif|png)$/, loader: "file-loader", options: {name: "./images/[name].[ext]"}},
]
},
devServer: {
historyApiFallback: true
},
plugins: [
new HtmlWebpackPlugin({
template: "./app/index.html"
}),
new webpack.LoaderOptionsPlugin({
options: {
sassLoader: {
includePaths: ["app/css"]
}
}
}),
new ExtractTextPlugin({
filename: "style.css",
allChunks: true
})
]
};
if (process.env.NODE_ENV === "production") {
config.plugins.push(
new webpack.DefinePlugin({
"process.env": {
"NODE_ENV": JSON.stringify(process.env.NODE_ENV)
}
}),
new webpack.optimize.UglifyJsPlugin()
);
}
module.exports = config;
Besides tweaking your configuration, you could use webpack --watch to have webpack watch your source files and recompile whenever you change something. The first compilation will still be a full one, but after that only the necessary parts will be recompiled each time, which can cut down compilation time from 30 seconds to 1 or 2 seconds.
Even better is to set up webpack's devserver with hot reloading, which also watches and incrementally compiles, but in addition will update your app in the browser, so you won't need to reload the page and lose react state. It can be a bit finicky to set up, but it's well worth the trouble.
I'm using webpack-dev-server in order to develop a React app on windows.
When running the command: webpack-dev-server --config webpack/webpack.dev.js,
then going to localhost, I'm getting an error message for the js file (the bundled one):
Not allowed to load local resource: file:///C:/Dev/react-starter/dist/main.js
I'm not fully familiar with webpack-dev-server, but didn't get a sense about why this can happen even from the docs and the GH issues.
my config looks like:
var path = require('path');
var WebpackDashboard = require('webpack-dashboard');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var srcFolder = path.resolve(__dirname, '../src');
var buildFolder = path.resolve(__dirname, '../dist');
var publicFolder = path.resolve(__dirname, '../assets');
module.exports = {
target: 'web',
entry: './index.js',
context: srcFolder,
devtool: 'source-map',
output: {
path: buildFolder,
publicPath: path.resolve(__dirname, '../dist/'),
filename: '[name].js',
chunkFilename: '[name].chunk.js',
},
resolve: {
extensions: ['.js', '.jsx', '.json', '.scss'],
alias: {
'#': srcFolder,
}
},
module: {
rules: [
{
test: /\.(js|jsx)/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.scss$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader' },
{ loader: 'sass-loader' },
]
}
]
},
plugins: [
new HtmlWebpackPlugin({
inject: 'body',
template: path.resolve(__dirname, '../src/index.html'),
}),
],
devServer: {
contentBase: path.join(__dirname, '../dist'),
port: 4464,
hot: true,
publicPath: buildFolder,
}
}
Hope someone can help. Tnx!
I got the same problem today, and I think I know where is the problem. It's the publicPath. When we have this value, the script tag in html file should be updated accordingly, but it seems like it's not easy to change something auto-generated by HtmlWebpackPlugin.
So easy fix is delete the publicPath value. Works for me.
I also got the same problem today. My solution is to move/copy the local resource to the public folder. After doing so, I also updated the path that references that resource accordingly in the js/html file to //<resource_name>.
It does not require to modify the webpack config. Hope it helps!^_^
I'm trying to make a theme for Ghost using React. I'm using webpack as my build tool of choice. How can I tell webpack to serve a specific .hbs file? As it seems now, Webpack only supports .html files. Below is my dev config... does webpack normally support anything that gets passed into it?
var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: [
'webpack-dev-server/client?http://localhost:2368',
'webpack/hot/only-dev-server',
'./src/router'
],
devtool: 'eval',
debug: true,
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js',
//publicPath: '/static/'
},
resolveLoader: {
modulesDirectories: ['node_modules']
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new HtmlWebpackPlugin({
template: './public/default.hbs',
//hash: true,
inject: 'body',
filename: 'default.hbs'
})
],
resolve: {
extensions: ['', '.js', '.sass', '.css', '.hbs']
},
module: {
loaders: [
// js
{
test: /\.js$/,
loaders: ['babel'],
include: path.join(__dirname, 'src')
},
// CSS
{
test: /\.sass$/,
include: path.join(__dirname, 'src'),
loader: 'style-loader!css-loader!sass-loader'
},
// handlebars
{
test: /\.hbs$/,
include: path.join(__dirname, 'public'),
loader: 'handlebars-template-loader'
}
]
},
node: {
fs: 'empty'
}
};
Webpack doesn't supports .html, the HtmlWebpackPlugin is the one that does html manipulations.
The basic purpose of HtmlWebpackPlugin is to attach the compiled files as script / link tags into the template file that it gets, it works with string replace, so it doesn't matter what file is that.
In one of my projects I use PHP as the template that HtmlWebpackPlugin injects into it the bundles.
So, theoretically, HtmlWebpackPlugin "supports" handlebars without understanding handelbars syntax.
What you can do, is after webpack injected the bundles into the handlebars template, you can read and us it as your template, and render the html with it using handlebar's node api.