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.
Related
I have an express server that is written in es5 and es6 combined. It consists of js and ts files. So now when I make a webpack build and start the server, it runs fine. But if my code throws an error then the error tracing is not correct i.e source of error (file, line and column number) is not showing correctly.
Is there a way to map the bundle with the source?
I have tried adding:
devTool: "source-map" to webpack config but it doesn't work, it seems to be working with the browser. Is there any way to achieve the same for server-side as well?
Here is my webpack.config.js
const nodeExternals = require("webpack-node-externals");
const webpack = require("webpack");
const path = require("path");
module.exports = {
stats: "detailed",
target: "node",
externals: [nodeExternals()],
entry: {
app: "./server.js",
backupCronApp: "./backup/cron/index.js"
},
output: {
path: path.join(__dirname, "/build"),
filename: "[name].js",
libraryTarget: "commonjs2",
},
plugins: [new webpack.EnvironmentPlugin(["NODE_ENV"])],
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: "babel-loader",
},
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
};
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 am using webpack for my PHP and React project. I want to load a background image from my .scss file with the webpack file-loader but for some reason I don't know, the img-folder does not get copied/exported to my dist-folder. Below is the webpack.config.js:
var webpack = require("webpack");
var path = require("path");
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var WatchLiveReloadPlugin = require('webpack-watch-livereload-plugin');
var DIST_DIR = path.resolve(__dirname, "dist");
var SRC_DIR = path.resolve(__dirname, "src");
var extractPlugin = new ExtractTextPlugin({
filename: 'main.css'
});
module.exports = {
entry: ['babel-polyfill', SRC_DIR + "/app/index.js"],
output: {
path: DIST_DIR + "/app",
filename: "bundle.js",
publicPath: "/dist"
},
watch: true,
module: {
rules: [
{
test: /\.js$/,
include: SRC_DIR,
loader: "babel-loader",
exclude: /node_modules/,
query: {
presets: ["react", "es2015", "stage-2"], plugins: ["transform-decorators-legacy", "transform-class-properties"]
}
},
{
test: /\.scss$/,
use: extractPlugin.extract({
fallback: "style-loader",
use: ["css-loader", "sass-loader", "resolve-url-loader"]
})
},
{
test: /\.css$/,
use: ["css-loader", "sass-loader", "resolve-url-loader"]
},
{
test: /\.(jpg|png)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'img/',
publicPath: 'img/'
}
}
]
}
]
},
plugins: [
extractPlugin,
new WatchLiveReloadPlugin({
port: 'localhost',
files: [
'./dist/app/*.css',
'./dist/**/*.js',
'./src/app/**/*.png',
'./src/app/**/*.jpg',
'./src/app/**/.*.scss',
'./src/**/*.php',
'./src//*.js'
]
})
]
};
I also tried loader: 'file-loader?name=/dist/img/[name].[ext]', but with no luck.
My file structure is like this:
-- dist
-- app
bundle.js
main.css
-- src
-- app
-- css
main.scss
-- img
someimage.jpg
Then in my .scss i tried this:
background-image: url('/img/someimage.jpg');
Does anyone have an idea what's wrong here?
Try to import the image file in one of your script files like
import '/path/to/img.jpg';
this will let Webpack know about the dependency and copy it.
The CSS/Sass loaders do not translate URLs that start with a /, therefore your file-loader won't be applied here.
The solution is to use relative paths for the imports if you want them to be processed by webpack. Note that CSS and Sass have no special syntax for relative imports, so the following are equivalent:
url('img/someimage.jpg')
url('./img/someimage.jpg')
If you want them to be resolved just like a module, webpack offers the possibility to start the import path with a ~, as shown in sass-loader - imports.
EDIT: Link to github repo where this example is hosted is here in case someone wants to run it
I'm getting the near exact same problem as another user (you can find the question here), in that running the webpack-dev-server does actually compile and watch files correctly (seeing the console output in the terminal), but the browser still can't view my site correctly. This is my webpack.config.js file:
var webpack = require('webpack'),
path = require('path'),
// webpack plugins
CopyWebpackPlugin = require('copy-webpack-plugin');
var config = {
context: path.join(__dirname,'app'),
entry: './index.js',
output: {
path: path.join(__dirname, 'public'),
filename: 'bundle.js',
publicPath: path.join(__dirname, 'public')
},
devServer: {
// contentBase: './public/'
},
plugins: [
// copies html to public directory
new CopyWebpackPlugin([
{ from: path.join(__dirname, 'app', 'index.html'),
to: path.join(__dirname, 'public')}
]),
// required bugfix for current webpack version
new webpack.OldWatchingPlugin()
],
module: {
loaders: [
// uses babel-loader which allows usage of ECMAScript 6 (requires installing babel-preset-es2015)
{test: /\.js$/, loader: 'babel', exclude: /node_modules/, query: { presets: ['es2015']}},
// uses the css-loader (loads css content) and style-loader (inserts css from css-loader into html)
{test: /\.css$/, loader: 'style!css', exclude: /node_modules/}
]
}
};
module.exports = config;
And this is my directory structure:
+--- webpack/
+--- app/
+--- index.html
+--- index.js
+--- styles.css
+--- package.json
+--- webpack.config.js
Currently, running webpack-dev-server outputs the following in the browser (note the lack of the public/ directory which is where webpack normally outputs my html and javascript bundle):
EDIT: Adding the devServer.contentBase property and setting it to public gets the browser to return a 403 error not found as shown here:
Okay, so I was able to reproduce the issue that you have on my project. To fix the issue I changed some things.
Here is what I have set up. I'm defining a bit less in the output and using jsx instead of js, but the results should be the same. You can replace my src with wherever your source code is.
const config = {
entry: './src/App.jsx',
output: {
filename: 'app.js'
},
module: {
loaders: [
{
test: /\.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react', 'stage-0'],
plugins: ['add-module-exports']
}
},
{
include: /\.json$/, loaders: ['json-loader']
},
{
test: /\.scss$/,
loaders: ['style', 'css?modules', 'sass']
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
loader: 'file?name=fonts/[name].[ext]'
}
]
},
plugins: [
new webpack.ProvidePlugin({
'Promise': 'exports?module.exports.Promise!es6-promise',
'fetch': 'imports?self=>global!exports?global.fetch!isomorphic-fetch'
}),
new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.DedupePlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
})
],
resolve: {
root: path.resolve('./src')
},
devServer: {
contentBase: 'src'
}
};
So basically you would want this output in terminal:
webpack result is served from / - tells us that whatever we build from will be at the root
content is served from src - tells us that it's building from that directory
Hope this helps
I'm trying to develop a react isomorphic app, and i've recently came up with the webpack-isomorphic-tools npm package.
I've tried to follow the documentation but unfortunately the images and style files doesn't get recognized, and not added to the webpack-assets.json file.
Up until now I've used this method:
if(process.env.BROWSER){
include('./style.scss');
}
But I understood webpack-isomorphic-tools is more beneficial.
for scss and other style files this is the error i get when running the server:
[webpack-isomorphic-tools] [debug] requiring ./shared/Root.scss
[webpack-isomorphic-tools] [error] asset not found: ./shared/Root.scss
for image files no errors are shown during the build, since no images are detected on the build. here is the webpack-assets.js:
{
"javascript": {
"main": "/build/bundle.js"
},
"styles": {},
"assets": {}
}
Relevant code:
webpack-isomorphic-tools-config.js:
var webpack_isomorphic_tools_plugin = require('webpack-isomorphic-tools/plugin');
module.exports =
{
debug: true,
webpack_assets_file_path : 'public/build/webpack-assets.json',
webpack_stats_file_path : 'public/build/webpack-stats.json',
assets:
{
images:
{
extensions: ['png', 'jpg', 'gif', 'ico', 'svg']
},
fonts:
{
extensions: ['woff', 'woff2', 'eot', 'ttf']
},
styles:
{
extensions: ['scss', 'less', 'css'],
filter(module, regular_expression, options, log)
{
if (options.development)
{
// In development mode there's Webpack "style-loader",
// which outputs `module`s with `module.name == asset_path`,
// but those `module`s do not contain CSS text.
//
// The `module`s containing CSS text are
// the ones loaded with Webpack "css-loader".
// (which have kinda weird `module.name`)
//
// Therefore using a non-default `filter` function here.
//
return webpack_isomorphic_tools_plugin.style_loader_filter(module, regular_expression, options, log)
}
// In production mode there will be no CSS text at all
// because all styles will be extracted by Webpack Extract Text Plugin
// into a .css file (as per Webpack configuration).
//
// Therefore in production mode `filter` function always returns non-`true`.
},
// How to correctly transform kinda weird `module.name`
// of the `module` created by Webpack "css-loader"
// into the correct asset path:
path: webpack_isomorphic_tools_plugin.style_loader_path_extractor,
// How to extract these Webpack `module`s' javascript `source` code.
// Basically takes `module.source` and modifies its `module.exports` a little.
parser: webpack_isomorphic_tools_plugin.css_loader_parser
}
}
}
index.js (looks a lot like the one in the documentation):
'use strict';
var path = require('path');
require('babel-register');
require('babel-polyfill');
require('app-module-path').addPath(path.join(__dirname,'shared'));
global._development_ = false
if (process.env.NODE_ENV !== 'production'){
global._development_ = true;
}
var Webpack_isomorphic_tools = require('webpack-isomorphic-tools');
// this must be equal to your Webpack configuration "context" parameter
var project_base_path = path.resolve(__dirname);
// this global variable will be used later in express middleware
global.webpack_isomorphic_tools = new Webpack_isomorphic_tools(require('./webpack-isomorphic-tools-config'))
// enter development mode if needed
// (you may also prefer to use a Webpack DefinePlugin variable)
.development(!(process.env.NODE_ENV === 'production'))
// initializes a server-side instance of webpack-isomorphic-tools
// (the first parameter is the base path for your project
// and is equal to the "context" parameter of you Webpack configuration)
// (if you prefer Promises over callbacks
// you can omit the callback parameter
// and then it will return a Promise instead)
.server(project_base_path, function()
{
// webpack-isomorphic-tools is all set now.
// here goes all your web application code:
// (it must reside in a separate *.js file
// in order for the whole thing to work)
require('./server/server')
});
webpack.dev.js (webpack-dev-server config):
var path = require('path');
var webpack = require('webpack');
var Webpack_isomorphic_tools_plugin = require('webpack-isomorphic-tools/plugin')
var webpack_isomorphic_tools_plugin =
// webpack-isomorphic-tools settings reside in a separate .js file
// (because they will be used in the web server code too).
new Webpack_isomorphic_tools_plugin(require('./webpack-isomorphic-tools-config'))
// also enter development mode since it's a development webpack configuration
// (see below for explanation)
.development();
module.exports = {
context: __dirname,
entry: ['webpack-dev-server/client?http://127.0.0.1:8080/',
'webpack/hot/only-dev-server',
'./client/index.jsx'],
resolve: {
modulesDirectories: ['node_modules', 'shared'],
extensions: ['', '.js', '.jsx']
},
output: {
path: path.join(__dirname, 'public', 'build'),
filename: 'bundle.js',
publicPath: "/build/"
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loaders: ['react-hot', 'babel']
},
{
test: /\.css$/,
loader: "style-loader!css-loader!autoprefixer-loader"
},
{
test: /\.less$/,
loader: "style-loader!css-loader!autoprefixer-loader!less-loader"
},
{
test: /\.scss$/,
loader: "style-loader!css-loader!autoprefixer-loader!sass-loader"
},
{
test: webpack_isomorphic_tools_plugin.regular_expressions['images'],
loader: "url-loader?limit=10240"
},
{
test: webpack_isomorphic_tools_plugin.regular_expression['fonts'],
loader: "url-loader?limit=10240"
}
]
},
plugins: [
new webpack.DefinePlugin({
"process.env": {
BROWSER: JSON.stringify(true),
NODE_ENV: JSON.stringify( process.env.NODE_ENV || 'development' )
}
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
webpack_isomorphic_tools_plugin
],
devtool: 'inline-source-map',
devServer: {
hot: true,
proxy: {
'*': 'http://127.0.0.1:' + (process.env.PORT || 3000)
},
host: '127.0.0.1'
}
};
webpack.config.js:
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var Webpack_isomorphic_tools_plugin = require('webpack-isomorphic-tools/plugin')
var webpack_isomorphic_tools_plugin =
// webpack-isomorphic-tools settings reside in a separate .js file
// (because they will be used in the web server code too).
new Webpack_isomorphic_tools_plugin(require('./webpack-isomorphic-tools-config'));
module.exports = {
context: __dirname,
entry: ['./client/index.jsx'],
resolve: {
modulesDirectories: ['node_modules', 'shared'],
extensions: ['', '.js', '.jsx']
},
output: {
path: path.join(__dirname, 'public', 'build'),
filename: 'bundle.js',
publicPath: "/build"
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loaders: ['react-hot', 'babel']
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!autoprefixer-loader")
},
{
test: /\.less$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!autoprefixer-loader!less-loader")
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader!autoprefixer-loader!sass-loader")
},
{
test: /\.gif$/, loader: "url-loader?limit=10000&mimetype=image/gif"
},
{
test: /\.jpg$/, loader: "url-loader?limit=10000&mimetype=image/jpg"
},
{
test: /\.png$/, loader: "url-loader?limit=10000&mimetype=image/png"
},
{
test: /\.svg/, loader: "url-loader?limit=26000&mimetype=image/svg+xml"
},
{
test: /\.(woff|woff2|ttf|eot)/, loader: "url-loader?limit=1&name=/[hash].[ext]"
}
]
},
plugins: [
new webpack.DefinePlugin({
"process.env": {
BROWSER: JSON.stringify(true),
NODE_ENV: JSON.stringify( process.env.NODE_ENV || 'development' )
}
}),
new ExtractTextPlugin("bundle.css")
]
};
If more code is required, I'd be happy to give it, thanks!