Hi I am trying to establish my project in react.
My Current project structure is
-public
--w
---dist
----bundle.js
---index.html
-server
--server.js
-src
--app.js
-webpack.config.js
-package.json
-.babelrc
I am using node js as server
I want my static files to called on localhost:port//w/
and api call on localhost:port//api/
I have tried manipulating server.js, routes, project structure and webpack.config but could not get success.
server.js
const express = require('express');
const path = require('path');
const app = express();
const port = 3000;
const publicPath = path.join(__dirname, '../public/w');
app.use(express.static(publicPath));
app.get('/w/*', (req, res) => {
console.log('Calling..');
res.sendFile(path.join(publicPath, 'index.html'));
})
app.get('/api/test', (req, res) => {
res.send("Hello");
})
app.listen(port, () => {
console.log(`Server is up on ${port}`);
})
webpack.config
const path = require('path');
module.exports = {
entry: './src/app.js',
output: {
path: path.join(__dirname, 'public', 'w', 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/
}
]
},
devtool: 'inline-source-map',
devServer: {
contentBase: path.join(__dirname, 'public', 'w'),
publicPath: '/dist/',
historyApiFallback: true
}
}
My routes
const AppRouter = (props) => {
return (
<BrowserRouter>
<div>
<Switch>
<Route path="/" component={Dashboard} />
<Route path="/w/resume-builder" component={ResumeBuilder} />
</Switch>
</div>
</BrowserRouter>
)
}
Can anyone suggest what should I do or What I am missing in it?
You have to do some restructure
-public
--dist
---bundle.js
--index.html
-server
--server.js
-src
--app.js
-webpack.config.js
-package.json
-.babelrc
Server.js
const express = require('express');
const path = require('path');
const app = express();
const port = 3000;
const publicPath = path.join(__dirname, '../public');
app.use(express.static(publicPath));
//keep all api before fallback
app.get('/api/test', (req, res) => {
res.send("Hello");
});
app.get('/w/*', (req, res) => {
console.log('Calling..');
res.sendFile(path.join(publicPath, 'index.html'));
});
app.listen(port, () => {
console.log(`Server is up on ${port}`);
});
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/app.js',
output: {
path: path.join(__dirname, 'public', 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/
}
]
},
devtool: 'inline-source-map',
devServer: {
contentBase: path.join(__dirname, 'public'),
publicPath: '/dist/',
historyApiFallback: true
}
}
You can keep your routes same.
Related
I have express ssr app. I want to host my static files in /static/* folder. But i have problem with React.Lazy component chunk request, it has wrong path
http://localhost:3000/staticreact.LazyChunk.js
My server code:
import express from 'express';
import path from 'path';
import handleRequest from '#server/infrastructure/handleRequest/handleRequest';
import {routes} from '#general-infrastructure/routes/routes';
import { handleErrors } from '#server/middlewares/errorHandler/errorHandler';
const server = express();
// if i'll comment this, reactlazy chunk will have normal path, but other static files will have 404 error status
server.use('/static', express.static(path.join(__dirname, '/static')));
// TODO -
// 5. redux for theme
server.get('*', handleErrors(async function(req, res, next) {
handleRequest(req.url, res, routes);
}));
server.listen(3000, () => {
console.log('Server running on http://localhost:3000');
});
if i'll comment server.use , reactlazy chunk will have normal path, but other static files will have 404 error status.
How can i fix it? ty
Noone extra slash not working
Webpack config:
module.exports = {
name: 'client',
entry: {
client: path.resolve(__dirname, 'src/client/index.tsx'),
},
mode: mode,
output: {
path: path.resolve(__dirname + '/dist/static'),
filename: '[name].[contenthash].js',
publicPath: path.resolve(__dirname, '/static'),
chunkFilename: 'react.[name].chunk.js',
clean: true,
},
resolve: {
extensions: ['.ts', '.tsx', '.js', '.jsx', '.css', '.scss'],
alias: webpackAliases,
},
Noone extra slash in webpack config not working
Router:
const Lazy = React.lazy(() => import(/* webpackChunkName: "LazyChunk" */ '#client/modules/pages/Lazy'));
const Routes: React.FC = () => {
const AppRoutes = useRoutes(
[
{path: '/', element: <Feed />},
{path: '/lazy', element: <Lazy />},
{path: '/overview', element: <Overview.component />},
],
);
return (
<Suspense fallback="Loading...">
{AppRoutes}
</Suspense>
);
};
React lazy load chunk error:
publicPath
the value of this option ends with /
Try adding /
publicPath: path.resolve(__dirname, '/static') + '/',
try to use only this,
server.use(express.static("/static"));
Here is my folder structure:
src/
└───public/
├───index.js
├───controllers/
├───css/
├───js/
├───models/
├───vendor/
└───views/
└───partials/
I know it's not the best folder structure, but it's one of my earlier projects, and I wanted to test webpack on it.
Anyways the controllers, js, vendor all contain javascript code.
My webpack.dev.config is on the same level as src:
const path = require("path");
const common = require("./webpack.common");
const {merge} = require("webpack-merge");
module.exports = merge(common, {
target: 'node',
mode: "development",
output: {
filename: "[name].bundle.js",
path: path.resolve(__dirname, "dist")
},
plugins: [
],
module: {
}
});
As you can see it merges from webpack.common.js:
const nodeExternals = require('webpack-node-externals');
module.exports = {
externals: [nodeExternals()],
entry: {
main: './src/index.js'
},
module: {
rules: [
{
test: /\.js$/,
}
]
}
}
For now I am hardcoding the location of the bundled js file in my HTML docs, but on the browser when I run this, I see the message Uncaught ReferenceError: require is not defined and I am not sure how to fix it.
Here is index.js:
const express = require('express');
const path = require('path');
const app = express();
const port = process.env.PORT || 8080;
const exphbs = require('express-handlebars');
const Datastore = require('nedb');
const db = new Datastore({
filename: path.join(__dirname, 'public/db/pfam.db'),
autoload: true
});
module.exports.db = db;
app.use(express.static(__dirname + "/public"));
app.set('views', path.join(__dirname, 'public/views'));
app.set('img', path.join(__dirname, 'public/img'));
app.set('js', path.join(__dirname, 'public/js'));
app.set('css', path.join(__dirname, 'public/css'));
app.set('controllers', path.join(__dirname, '/public/controllers'));
app.set('db', path.join(__dirname, '/public/db'));
app.engine('handlebars', exphbs({
defaultLayout: 'home',
layoutsDir: path.join(__dirname, '/public/views')
}))
app.set('view engine', 'handlebars');
app.use(require('./public/controllers'))
console.log(`listening on port ... ${port}`)
app.listen(port);
The reason you are getting Uncaught ReferenceError: require is not defined is because your bundles contains require keyword, which is undefined in the browser?
Why do they contain require?
Because you use nodeExternals from webpack-node-externals
From their docs:
All node modules will no longer be bundled but will be left as require('module').
I have a React app, served via ExpressJS. I have configured Webpack to create .gz assets.
However HtmlWebpackPlugin creates the bundle in my index.html as a .js file.
I assume this is because in the output prop in my webpack.prod.js I have the filename with a .js extention.
How can I configure this to return the .gz extension when supported?
Express App
const express = require('express');
const path = require('path');
const app = express();
app.use(express.static(path.resolve(__dirname, '../dist')));
app.get('*.js', function(req, res, next) {
req.url = req.url + '.gz';
res.set('Content-Encoding', 'gzip');
next();
});
app.get('/healthz', (req, res) => res.send('OK'));
app.get('*', (req, res) =>
res.sendFile(path.resolve(__dirname, '../dist/index.html'))
);
const PORT = process.env.SERVER_PORT || 3000;
const HOST = process.env.SERVER_HOST || '127.0.0.1';
app.listen(PORT);
console.log(`API started on ${HOST}:${PORT}`);
webpack.common.js
const commonPaths = require('../common-paths');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
context: commonPaths.appPath,
entry: './index.jsx',
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [
{ test: /\.(jsx?)$/, exclude: /node_modules/, use: ['babel-loader'] }
]
},
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
chunks: 'initial',
test: 'vendor',
name: 'vendor',
enforce: true
}
}
}
},
plugins: [
new CompressionPlugin({
algorithm: 'gzip',
test: /\.js$|\.css$|\.html$/,
threshold: 10240,
minRatio: 0.8
}),
new HtmlWebpackPlugin({
title: 'Web App',
template: commonPaths.projectRoot + '/public/index.html',
inject: 'body'
})
]
};
webpack.prod.js
const commonPaths = require('../common-paths');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
devtool: 'source-map',
mode: 'production',
output: {
filename: 'static/[name].[hash].min.js',
path: commonPaths.outputPath
},
plugins: [
new ExtractTextPlugin({
filename: 'static/styles.[hash].min.css',
allChunks: true
})
]
};
I have also tried the following in my Express App incase it was failing in serving the files...
const express = require('express');
const path = require('path');
const app = express();
app.use(
express.static(path.resolve(__dirname, '../dist'), {
index: false,
fallthrough: true,
setHeaders: (res) => {
res.set('Content-Encoding', 'gzip');
}
})
);
app.get('/healthz', (req, res) => res.send('OK'));
app.get('*', (req, res) =>
res.sendFile(path.resolve(__dirname, '../dist/index.html'))
);
const PORT = process.env.SERVER_PORT || 3000;
const HOST = process.env.SERVER_HOST || '127.0.0.1';
app.listen(PORT);
console.log(`API started on ${HOST}:${PORT}`);
I configured webpack dev middleware, when I go to index page / all works fine, otherwise page Not Found, how to make work dev server for all paths ?
const Koa = require('koa');
const webpack = require('webpack');
const devMiddleware = require('koa-webpack-dev-middleware')
const path = require('path');
const fs = require('fs');
const PORT = 3000;
const app = new Koa();
const config = require('./webpack.config');
const compiler = webpack(config);
app.use(devMiddleware(compiler, {
publicPath: config.output.publicPath,
historyApiFallback: true,
stats: { colors: true },
}));
app.listen(PORT, function () {
console.log(`Dev Server port: "${3000}"`);
});
webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
},
devtool: 'inline-source-map',
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Output Management'
})
],
module: {
rules: [
{
test: /.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|svg|jpg|gif)$/,
use: ['file-loader']
},{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: ['file-loader']
}
]
}
}
I'm trying to set up HMR with my express sever. When I run node app, I see that webpack compiles, SQL seeds DB and node runs in my terminal . My app runs and seems to work, however when I make a change I don't see the change. I also don't see the change when I refresh the app either!
What am I missing? I think I'm close.
note: I'm following : http://andrewhfarmer.com/understanding-hmr/
index.js:
import React from 'react'
import ReactDOM from 'react-dom'
import routes from './config/routes'
ReactDOM.render(
routes,
document.getElementById('root')
);
if (module.hot) {
module.hot.accept();
}
webpack.config
var webpack = require('webpack')
var ExtractTextPlugin = require("extract-text-webpack-plugin")
var HtmlWebpackPlugin = require('html-webpack-plugin')
var HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
template: __dirname + '/index.html',
filename: 'index_bundled.html',
inject: 'body',
})
module.exports = {
entry: {
"jquery": __dirname + '/public/js/lib/jquery/jquery-2.0.3.min.js',
"bootstrap": __dirname + '/public/bootstrap/js/bootstrap.min.js',
"index": [__dirname + '/app/index.js',
'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=2000&overlay=false'],
},
output: {
path: __dirname + '/public',
filename: '[name].js',
publicPath: '/',
},
module: {
loaders: [
{test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
{test: /\.css$/, loader: 'style!css?sourceMap&modules&localIdentName=[name]__[local]___[hash:base64:5]'},
],
},
devtool: 'cheap-module-inline-source-map',
plugins: [
HTMLWebpackPluginConfig,
new ExtractTextPlugin("dist/[name].css"),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
]
}
app.js
var express = require('express');
var webpack = require('webpack');
var webpackDevMiddleware = require("webpack-dev-middleware");
var webpackHotMiddleware = require("webpack-hot-middleware");
var compiler = webpack(require("./webpack.config.babel.js"));
/* Sequelize stuff */
var app = module.exports = express();
app.use(webpackDevMiddleware(compiler, {
hot: true,
filename: 'index.js',
publicPath: '/',
stats: {
colors: true,
},
historyApiFallback: true,
}));
//app.use(require("webpack-hot-middleware")(compiler));
app.use(webpackHotMiddleware(compiler, {
log: console.log,
path: '/__webpack_hmr',
heartbeat: 2000,
}));
/* APIs and routes */
// Starting express server
http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'));
});