React WebPack - Send My Work to online Server - javascript

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.

Related

How to use Express to serve a frontend compiled by Webpack?

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!

Static resources not showing up in Chrome Dev Tools

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.

html-webpack-plugin not inject js file into index.html when using webpack-dev-server

Here is my webpack config :
var path = require('path');
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var fs = require('fs'),buildPath='./dist/';
var folder_exists = fs.existsSync(buildPath);
if(folder_exists == true)
{
require('shelljs/global')
rm('-rf', 'dist')
};
module.exports = {
entry: './src/main',
output: {
path: path.join(__dirname, './dist'),
filename: '[name].js',
publicPath: '/dist/'
},
devServer: {
historyApiFallback: true,
hot: false,
inline: true,
grogress: true,
},
// "vue-hot-reload-api": "^1.2.2",
module: {
loaders: [
{ test: /\.vue$/, loader: 'vue' },
{ test: /\.js$/, loader: 'babel', exclude: /node_modules/ },
{ test: /\.css$/, loader: 'style-loader!css-loader'},
//install css-loader style-loader sass-loader node-sass --save-dev
{ test: /\.scss$/, loader: 'style!css!sass?sourceMap'},
{ test: /\.(png|jpg|gif)$/, loader: 'url-loader?limit=8192&name=images/[name].[ext]'},
{ test: /\.(html|tpl)$/, loader: 'html-loader' },
]
},
vue: {
loaders: {
js:'babel',
css: 'style-loader!css-loader',
sass:'style!css!sass?sourceMap'
}
},
babel: {
presets: ['es2015'],
plugins: ['transform-runtime']
},
plugins:[
new HtmlWebpackPlugin({
template: 'index.html',
filename: './index.html',
inject:true
}),
],
resolve: {
extensions: ['', '.js', '.vue'],
alias: {
filter: path.join(__dirname, './src/filters'),
components: path.join(__dirname, './src/components')
}
},
devtool: 'eval-source-map'
};
And in package.json:
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "webpack-dev-server --inline",
"build": "webpack --config webpack.config.prod.js"
},
When I run npm start, in localhost the js file is not injected in index.html.
If I run webpack or npm run build, the js file is injected successfully.
Can html-webpack-plugin also inject js file into index.html when I'm in localhost?
This issue is related specifically to the fact that the webpack-development-server does not have the ability to write files to your local file system and instead writes its files to MEMORY Only.
This is why you were able to properly generate files wth Html-Webpack-Plugin when you run the default webpack build command (NOT the WDS / Webpack-Development-Server) with:
webpack
Alternately since you were using vue.js Webpack-simple project (https://github.com/vuejs-templates/webpack-simple/tree/master/template) you were also able to use the npm scripts that come with the Vue.js sample (located inside of your package.json) via:
npm run build
In either case the files ARE written to the directory as you would have thought they should be since Building with webpack CAN write the file system, where as no files were written when using Webpack-Development-Server (again this does not work because WDS writes to memory and not the local file system).
I stumbled onto this answer when working on the same problem thanks to your comment:
"If I run webpack or npm run build, the js file is injected successfully. Can html-webpack-plugin also inject js file into index.html when I'm in localhost?"
To sum up:
Html-Webpack-Plugin WILL NOT write files to the local file system when it is used as a part of the Webpack-Development-Server (WDS) even though Html-Webpack-Plugin WILL write files (with an identical webpack configuration) when using the normal webpack build process (no WDS).
I have same problem and below config work for me.
I used to have absolute path and when change it to relative, it work.
new HtmlWebpackPlugin({
inject: true,
template:'public/index.html', // relative to project root
filename:'index.html' // relative to build folder
})
You can try config like this..
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
})
and Index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>My App</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
You will need install npm i -D html-webpack-plugin vue-loader vue-html-loader
but I recommend you create a project from template, vue init webpack
This template use the html-webpack-plugin

Webpack, new chunk is loading in with wrong path

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

Include assets from webpack bundled npm package

I've been banging my head over this for a while, and am wondering if it's even possible to begin with. Thanks for any help with this!
The npm package
I've got an npm package which is basically a library of React components. This library has embedded stylesheets, which references assets like fonts and images from the CSS. These are then all bundled using webpack into my-package.js.
The config for this looks like:
var path = require('path');
module.exports = {
module: {
loaders: [
{
test: /\.js$/,
loaders: ['babel-loader'],
exclude: /node_modules/
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/,
loader: 'file-loader'
},
{
test: /\.styl$/,
loader: 'style-loader!css-loader!stylus-loader'
}
]
},
entry: [
'./lib/components/index.js',
'./lib/index.styl'
],
output: {
path: path.join(__dirname, 'build/'),
filename: 'my-package.js'
}
}
With ./lib/components/index.js looking like:
import '../index.styl';
import MyComponent from './my-component.js';
export {
MyComponent
}
So far, so good.
The application
Now in another code base I've got the main application, which install this npm package.
My application root requires this package...
import MyPackage from 'my-package';
And is then itself webpack bundled and loaded onto the browser. All the scripts and style blocks are bundled correctly, however the styles which reference the assets are using the relative url from the npm package itself, therefore giving me 404s from the application.
console errs
Is there any way to tell webpack to resolve these images from node_modules/my-package/build/[webpack-generated-name].jpg ?
My application's webpack config looks like this:
var path = require('path'),
webpack = require('webpack');
module.exports = {
devtool: '#eval-source-map',
entry: [
'my-package',
'webpack/hot/only-dev-server',
'./app/index.js',
],
output: {
path: path.join(__dirname, 'build/static'),
filename: 'bundled.js',
publicPath: '/',
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
resolve: {
extensions: ['', '.js']
},
resolveLoader: {
'fallback': path.join(__dirname, 'node_modules')
},
module: {
loaders: [
{
test: /\.js$/,
loaders: ['react-hot', 'babel'],
exclude: /node_modules/,
include: __dirname
},
{
test: /\.css?$/,
loader: "style-loader!css-loader",
include: __dirname
},
{
test: /\.(jpg|jpeg|ttf|eot|svg|woff(2)?)(\?[a-z0-9]+)?$/,
loader: 'file-loader'
},
{
test: /\.styl$/,
loader: 'style-loader!css-loader!stylus-loader'
}
]
}
};
Figured out a way around this.
In my application's webpack config I added a plugin (recommended by #Interrobang) which copies the static assets from the node_module/my-package into the app server's public path:
var TransferWebpackPlugin = require('transfer-webpack-plugin');
...
plugins: [
new TransferWebpackPlugin([
{ from: 'node_modules/my-package/assets', to: path.join(__dirname, 'my/public') }
])
]
...
These will then be made accessible by calling the asset name: localhost:XXXX/my-image.jpg. The server here is basically looking at /my/public/my-image.jpg if you've set it up correctly.
I'm using Express, so I just had to define app.use(express.static('my/public')) in my app server.
When bundling your NPM package, you could inline all the static assets into your final bundle. That way, your index.js that Webpack bundles for you would have all the static assets it needs, and simply importing that wherever you need your React components would do the trick.
The best way to inline static assets as of Webpack 5 is by using the "asset/inline" module from Asset Modules, which you can read about here: https://webpack.js.org/guides/asset-modules/
Simply put, your webpack.config.js should have a section as such:
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
},
module: {
rules: [
{
test: /\.(png|jpg|gif)$/i,
type: 'asset/inline'
}
]
},
};
What really relates to your question here is the test for png, jpg, and gif files which uses the asset/inline module.
The post here https://stackoverflow.com/a/73417058/14358290 explains it with slightly more detail.
Other plugins that copy such files from your /node_modules to /build directory are hacky and create packages that are not really distributable - everyone else that uses the said package would have to set up their Webpack to do the same copying operation. That approach can be avoided now that Webpack 5 solves this problem for us.

Categories

Resources