Messing round with a simple react + webpack app, however I'm having issues debugging because the static resources don't seem to be loading in dev tools (and I can't work out why breakpoints aren't working!)
Got the following in my webpack.config.js file:
var ExtractTextPlugin = require('extract-text-webpack-plugin');
const webpack = require('webpack');
const path = require('path');
module.exports = {
devtool: 'eval-source-map',
entry: path.join(__dirname, 'src', 'app.js'),
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
loaders: [
{
test: path.join(__dirname, 'src'),
loader: ['babel-loader'],
query: {
cacheDirectory: 'babel_cache',
presets: ['react', 'es2015']
}
},
{
test: /\.css/,
loader: ExtractTextPlugin.extract("style-loader", "css-loader")
},
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
loader: 'file-loader'
}
]
},
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
}),
new webpack.optimize.DedupePlugin(),
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.optimize.UglifyJsPlugin({
compress: { warnings: false },
mangle: true,
sourcemap: false,
beautify: false,
dead_code: true
}),
new ExtractTextPlugin("styles.css")
]
};
And my express app serves up the /dist folder:
app.use('/static', Express.static(path.join(__dirname, '..', 'dist')));
However, when I try to view the source code (using a sourcemap), my dev tools is only showing the following:
When I navigate to localhost:3000/static/bundle.js and localhost:3000/static/bundle.js.map it shows the files in plaintext. My app also 'works' (ie. the JS is being used) but it doesn't seem to show in Chrome. Am I missing something very obvious here?
Thanks for any help!
So found a way to do this, just incase you're reading this in the future.
The issue I had was that I was using index.ejs to display the markup:
index.ejs
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Title</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div id="main"><%- markup -%></div>
</body>
</html>
server.js
return res.render('index', { markup });
I wasn't including dist/bundle.js into my .ejs file, and this meant that Chrome Tools didn't pick it up. I added <script src="static/bundle.js"></script> to my index.ejs (even though not strictly necessary for the code to work!) and it began to appear in chrome dev tools at last.
I can now finally set breakpoints in my code and debug, as well as opening my .js files in the Source tab, so all appears to be working fine.
I'd be interested to hear if there's another way of doing this, one that doesn't involve needlessly getting the bundle.js script in the html.
Related
I am trying to get more familiar with using webpack. I have converted everything to be able to load modules, and plugins. Everything loads fine when I run "npm run build-prod", when I use liveServer, HTML and everything loads properly. However when I run "npm run build-dev", it auto pops up my index.html file and starts reloading the page nonstop, and doesn't apply any CSS. The reloading issue makes me think I am using npm run build-dev wrong.
I am pretty new to webpacks, but to my understanding, the point of running "npm run build-dev", it will compile everything using my loaders and plugins without minifying everything, so I can edit and make changes in real time. Or is my understanding completely wrong.
const path = require("path");
const webpack = require("webpack");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
module.exports = {
entry: "./src/client/index.js",
mode: "development",
devtool: "source-map",
stats: "verbose",
output: {
filename: "main.js",
path: path.resolve(__dirname, "dist"),
},
module: {
rules: [
{
test: "/.js$/",
exclude: /node_modules/,
loader: "babel-loader",
},
{
test: /\.scss$/,
use: ["style-loader", "css-loader", "sass-loader"],
},
],
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/client/views/index.html",
filename: "./index.html",
}),
new CleanWebpackPlugin({
// Simulate the removal of files
dry: true,
// Write Logs to Console
verbose: true,
// Automatically remove all unused webpack assets on rebuild
cleanStaleWebpackAssets: true,
protectWebpackAssets: false,
}),
],
};
Here is my full repo, but without the .env variables holding my API keys.
Just a friendly advice: It feels like you started doing something complex without getting the basics right.
Why don't you try some of the examples first?
The webpack website is quite rich of those: https://webpack.js.org/guides/getting-started/
Never figured out what the issue was, but when I ran it on my Mac instead of Windows, I couldn't reproduce the issue. I tried on both Chrome and FireFox without any plug-in.
I have the following webpack.config.js
const path = require("path");
const webpack = require("webpack");
const HtmlWebPackPlugin = require("html-webpack-plugin");
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
entry: "./src/index.js",
mode: "development",
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules)/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
},
resolve: { extensions: ["*", ".js"] },
output: {
path: path.resolve(__dirname, "public/dist/"),
publicPath: "/dist/",
filename: "bundle.js"
},
devServer: {
contentBase: __dirname,
port: 3000,
publicPath: "http://localhost:3000/dist/",
proxy: {
'/api' : {
target: 'http://localhost:8000',
secure: false
}
},
hot: true
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebPackPlugin({
hash: true,
template: "./src/index.html",
filename: "index.html"
})
],
optimization: {
minimize: true,
minimizer: [new TerserPlugin()]
}
};
When I run webpack-dev-server, everything compiles fine, but when I navigate to localhost:3000/public/dist/index.html, I get a "file not found" error.
However, when I run webpack --mode development, the index.html file is correctly written to public/dist and I'm able to open it on my web browser.
I'm not sure why this file is correctly written when webpack is run normally, but not when the dev server is ran. I know the webpack dev server serves files from memory so I don't expect it to show up on my filesystem but I at least expect to be able to open it from the browser.
Thanks!
Webpack dev server doesn't actually build the files to your project directory. From their docs:
webpack-dev-server doesn't write any output files after compiling. Instead, it keeps bundle files in memory and serves them as if they were real files mounted at the server's root path.
So running webpack-dev-server, you shouldn't expect to see any built files (like your resultant index.html) in your dist directory. It will be serving the project from memory directly to your localhost:3000, or whatever pathname you choose. However, running webpack actually builds the files to your destination directory, and you'll find them there. Hope that clears it up for you.
I have the following Express app which serves static files, specifically public/index.html.
server.js
const express = require('express');
const app = express();
const port = 8000;
app.use(express.static('public'));
app.listen(port, () => {
console.log(`Example app listening # http://localhost:${port}`);
});
public/index.html
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
</head>
<body>
<script src="./dist/bundle.js"></script>
<script>
// possibly make API calls to http://localhost:8000
</script>
</body>
</html>
This HTML file requires a script located at ./dist/bundle.js.
The bundle is compiled using Webpack, which has this configuration:
webpack.config.js
const path = require("path");
const webpack = require("webpack");
const TerserPlugin = require("terser-webpack-plugin");
module.exports = {
entry: "./src/index.js",
mode: "development",
module: {
rules: [
{
test: /\.(js)$/,
exclude: /(node_modules)/,
loader: "babel-loader",
options: { presets: ["#babel/env"] }
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
},
resolve: { extensions: ["*", ".js"] },
output: {
path: path.resolve(__dirname, "public/dist/"),
publicPath: "/dist/",
filename: "bundle.js"
},
devServer: {
contentBase: __dirname,
port: 3000,
publicPath: "http://localhost:3000/dist/",
hot: true
},
plugins: [new webpack.HotModuleReplacementPlugin()],
optimization: {
minimize: true,
minimizer: [new TerserPlugin()]
}
};
As you can see in output.path, the bundle's compiled output should go into public/dist which is inside the static file directory served by Express. That way, index.html can access it.
Now the problem is, my development workflow is incredibly inefficient.
webpack --mode development to write the latest bundle.js into public/dist
node server.js to re-run the server (in case there were any server-side changes)
If I were using webpack-dev-server alone without my own backend, I would get all the nice benefits of hot reloading, HMR, etc, and I don't have to worry about recompiling.
I know I can run webpack-dev-server and server.js concurrently on two different ports, but index.html would be served from server.js and wouldn't be able to access the in memory dist/bundle.js served by the webpack dev server.
Is there a way to serve a Webpack-compiled frontend from an Express server and still get all the nice benefits of using Webpack-dev-server, specifically hot reloading?
Thanks!
I have a online server where i put my works and portfolio and stuff , i have made a simple app in react and i want to run it in my server, but im getting the error
http://hseleiro.pt/bundle.js 404 (Not Found)
What im i doing wrong ? i dont know if im making the correct steps to show my react app in a online server, could some one help me ?
I have tried to change my pat on my Webpack.config.js but with no sucess.
Index.HTML
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="http://www.hseleiro.pt/ReduxSimpleStarter/style/style.css">
<link rel="stylesheet" href="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/css/bootstrap.css">
</head>
<body>
<div class="container"></div>
</body>
<script src="/bundle.js"></script>
</html>
WebPack.Config.Js
module.exports = {
entry: [
'./src/index.js'
],
output: {
path: __dirname,
publicPath: '/',
filename: 'bundle.js'
},
module: {
loaders: [{
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015', 'stage-1']
}
}]
},
resolve: {
extensions: ['', '.js', '.jsx']
},
devServer: {
historyApiFallback: true,
contentBase: './'
}
};
Thank you !!
I believe you want to expose the main index.html file you are using for your site and the bundle file on your server. The index file should contain a script tag, like this <script src="/bundle.js"></script> that references the source bundle you created with Webpack. When the site loads the bundle, your react app should start running.
I am trying to chunk my app - attempting to follow webpacks guide on how-to (https://webpack.github.io/docs/code-splitting.html). So I have a seperate chunk set up for my app, I can see that webpack is generating 1.bundle.js in my build folder, however it is pasting it onto my index.html with an incorrect path, and in my console I see the fetch error for the 1.bundle.js file.
So my webpack config looks like so (im just using the webpack:dev for now):
return {
dev: {
entry: {
index: './client/app.jsx'
},
output: {
path: path.join(__dirname, '..', '..', 'dist', 'client'),
publicPath: "/dist/client/",
filename: 'bundle.js'
},
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}, {
test: /\.json$/,
loader: 'json-loader'
}]
},
resolve: {
extensions: ['', '.js', '.jsx']
},
resolveLoader: {
fallback: [path.join(__dirname, 'node_modules')]
},
plugins: [
new webpack.DefinePlugin({
"process.env": {
"NODE_ENV": JSON.stringify("dev")
}
})
]
},
and in my index.html I manually add <script src="bundle.js"></script> and that has been working great. It looks like when this builds now, webpack is applying its own script tag on my index like so
<script type="text/javascript" charset="utf-8" async="" src="/dist/client/1.bundle.js"></script>
However this path is incorrect, it should just be src="1.bundle.js". I have tried tweaking the path and publicPath but nothing seems to work. Is there a way to have webpack add the correct path? Thanks!
You should change publicPath for this snippet:
publicPath: "/"
It will always serve your chunks from root path.
Even though it is answered and accepted, I am providing additional helpful info for others with similar problems.
There are two different purposes for which the 2 parameters are used.
Output:path : The directory the bundle files mentioned in entry section are saved into. For example, the bundle.js for the 'entry' entry you had mentioned. In this case, it will be saved in webconfigfolder+"../../dist/client" folder.
Output: publicPath: The directory prefix that is added to refer to a module when accessed from browser. 0.bundle.js is an unnamed chunk created by code splitting. It will be placed in the output:path mentioned above but will be referred in your html using the public path.
So,if your files as in this case is stored in /dist/client folder, but the index.htm is served in /dist/client, you should give the public path as ./. If htm is served from /dist, the public path should be given as ./client/.
The public path is useful for chunks created for async loading which are called from browser dynamically.
This is because you have given reference to publicPath. So it will try to load the script from this publicPath though the file is not present there.
Removing publicPath can resolve the error