Setting up assets paths for webpack-dev-server - javascript

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

Related

webpack hot reload uses incorrect url [duplicate]

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.

Webpack - browser refresh on a file change which isn't module

I want to refresh page when I change (save) ./src/*.js files in my code editor.
The problem is I'm not importing this files in my entry point (with import in index.js) but I'm joining them with a plugin so code is in browser's global scope rather then in module.
Basically I want to split longer JavaScript code into smaller files, I don't want to have modules.
I've tried many configurations and closest to my needs is that below, except that it doesn't refresh browser, (it recompiles).
How can I achieve recompile and refresh on JavaScript which should be in globalscope of the browser (or all code in one module)?
webpack.config.js:
const path = require('path');
const MergeIntoSingleFilePlugin = require('webpack-merge-and-include-globally');
const FileWatcherPlugin = require("file-watcher-webpack-plugin");
module.exports = {
context: __dirname,
entry: { bundle: './src/index.js' },
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}]
},
plugins: [
new MergeIntoSingleFilePlugin({
files: {
"app.js": [
path.resolve(__dirname, './src/setup.js'),
path.resolve(__dirname, './src/buttons.js'),
path.resolve(__dirname, './src/circle.js'),
path.resolve(__dirname, './src/wall.js')
]
}
}),
new FileWatcherPlugin({
root: __dirname,
files: ['*.js']
})
],
devServer: {
contentBase: './dist',
watchOptions: {
aggregateTimeout: 300,
poll: 1000
},
hot: true,
inline: true,
// publicPath: "./src",
watchOptions: {
ignored: './node_modules/'
}
}
};
npm start:
webpack-dev-server --open --inline --hot --watch --progress
and the setup.js, buttons.js etc are regular JS script files, not exported classes.
Any ideas appreciated!

Webpack dev server - Not allowed to load local resource

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!^_^

How to make Webpack work with .hbs files?

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.

All my code runs twice when compiled by Webpack

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".

Categories

Resources