i am trying render my React code on express server below is the code for that
const express =require('express');
const react =require('react');
const renderToString =require('react-dom/server').renderToString;
const HelloWorld=require('./client/components/Home');
const app = express();
app.get('/', (req, res) => {
const content=renderToString(<HelloWorld/>);
res.send(content);
});
app.listen(3000, () => {
console.log('Listening on prot 3000');
});
webpack.server.js
const path = require('path');
module.exports = {
// Inform webpack that we're building a bundle
// for nodeJS, rather than for the browser
target: 'node',
// Tell webpack the root file of our
// server application
entry: './src/index.js',
// Tell webpack where to put the output file
// that is generated
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'build'),
},
module:{
rules:[
{
test:/\.js?$/,
loader:'babel-loader',
exclude:/node_modules/,
options:{
presets:[
'react',
'stage-0',//asyc purpose,
['env',{targets:{browsers:['last 2 versions']}}]
]
}
}
]
}
};
package.json
"dev:build:server": "webpack --config webpack.server.js"
when i run my application using node build\bundle.js i am getting react is not defined even i am importing react in index.js
Changing
const react=require('react');
to
const React=require('react');
solved my problem
Related
why process.env doesn't work in app.js file but works in webpack.config.js? I have my own webpack that I created myself. It was not created with CRA
the version so it is correct to deduce? Or is there any way to get it out? Or is it better not to drive at all? since it seems to me that this is also not correct, since the env file should be in the exception and on the server, when loading, probably nothing will be known about the version ...
I want to output the version to the console so I can see the webpack version. But I can't do it even though I made the necessary settings. if I output data in webpack, then everything works correctly if I output data in a simple js file, erroneous errors. in general, I want to make the version visible on the server after the build, and I want to do it in this way, you can simply output console.log, but this seems like the wrong solution console.log('ver 1.74.2')
import React from "react";
import styles from "./styles.scss";
const onClickEvent = (e) => {
e.preventDefault();
alert("You Clicked Me!");
};
const App = () => {
console.log(process.env.TERM_PROGRAM_VERSION);
return (
<div className={styles.content}>
<div className={styles.label}>OWN WEBPACK</div>
<button className={styles.btn} onClick={onClickEvent}>
Click Me 😎
</button>
</div>
);
};
export default App;
const webpack = require("webpack");
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
const production = process.env.NODE_ENV === "production";
const Dotenv = require("dotenv-webpack");
console.log(process.env.TERM_PROGRAM_VERSION);
module.exports = {
entry: { myAppName: path.resolve(__dirname, "./src/index.js") },
output: {
path: path.resolve(__dirname, "./dist"),
filename: production ? "[name].[contenthash].js" : "[name].js",
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ["babel-loader"],
},
{
test: /\.s(a|c)ss$/,
exclude: /node_modules/,
use: [
production ? MiniCssExtractPlugin.loader : "style-loader",
{
loader: "css-loader",
options: {
modules: true,
sourceMap: !production,
},
},
{
loader: "sass-loader",
options: {
sourceMap: !production,
},
},
],
},
],
},
resolve: {
extensions: ["*", ".js", ".jsx", ".scss"],
},
plugins: [
new CleanWebpackPlugin(),
new Dotenv(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
title: "Webpack & React",
template: "./src/index.html",
favicon: "./public/favicon.ico",
}),
new MiniCssExtractPlugin({
filename: production ? "[name].[contenthash].css" : "[name].css",
}),
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
"process.env.MY_ENV": JSON.stringify(process.env.MY_ENV),
}),
],
devServer: {
port: 3001,
hot: true,
},
mode: production ? "production" : "development",
};
"scripts": {
"start": "npm run build && node server/index.js",
"dev": "NODE_ENV=development test=$TERM_PROGRAM_VERSION webpack serve --config webpack.config.js",
"build": "NODE_ENV=production webpack --config webpack.config.js",
"build:dev": "NODE_ENV=development webpack --config webpack.config.js",
"build:watch": "NODE_ENV=development node ./node_modules/webpack/bin/webpack.js --config webpack.config.js --watch"
},
//server/index.js
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const app = express();
if (process.env.NODE_ENV === 'development') {
console.log('in development.');
} else {
console.log('in production.');
}
/* App Config */
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, '../dist')));
/* Server Initialization */
app.get('/', (req, res) => res.sendFile('index.html'));
var port = process.env.PORT || 3000;
app.listen(port, () => console.log(`Server initialized on: http://localhost:${port} // ${new Date()}`));
Change your env variable to REACT_APP_TERM_PROGRAM_VERSION then reload your app.
React env variables must start with REACT_APP_ prefix. See https://create-react-app.dev/docs/adding-custom-environment-variables/
Still in my journey of deploying my ssr app on firebase. Almost there.
I only have an issue with my images. I am getting a 400 error message on the console. Pictures are from an external url. The data fetched is correct but it does display somehow. You will see below my server.js file and next.config.js.
Can someone tell me what is missing, please?
server.js
const { https } = require('firebase-functions');
const { default: next } = require('next');
const isDev = process.env.NODE_ENV !== 'production';
const server = next({
dev: isDev,
//location of .next generated after running -> yarn build
conf: { distDir: '.next' },
image :{ domain :['assets.coingecko.com'],}
});
const nextjsHandle = server.getRequestHandler();
exports.nextServer = https.onRequest((req, res) => {
return server.prepare()
.then(() => {
return nextjsHandle(req, res)
});
});
next.config.js
const webpack = require('webpack');
const path = require('path');
//const withPlugins = require('next-compose-plugins');
//const optimizedImages = require('next-optimized-images');
module.exports = {
images: {
domains: ['assets.coingecko.com'],
loader: 'imgix',
path: 'https://assets.coingecko.com/',
},
reactStrictMode: true,
entry: './src/index.js',
sassOptions: {
includePaths: [path.join(__dirname, 'styles')],
},
module: {
rules: [
//...
{
test: /\.(png|jp(e*)g|svg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'images/[hash]-[name].[ext]',
},
},
],
},
],
},
//...
}
first i wanted to thank you for your help #juliomalves. I found answer to my issue. I have answered the questions in details here [1][ https://stackoverflow.com/questions/69974890/how-to-set-up-next-image-loader-url-correctly-for-external-url/70052871#70052871]
if anyone find himself in the same situation.
For the life of me, I can't seem to get hot reloading to work. Does anyone have any ideas? What I do get in the console is "[HMR] connected", but when i make a change to a react component, the entire page refreshes.
I understand that I should something along the lines of:
[HMR] bundle rebuilding
[HMR] bundle rebuilt in 5269ms
.....
But I don't see any of this.
Here are my configs:
server.js
var path = require('path')
var webpack = require('webpack')
var express = require('express')
var config = require('./webpack.config')
var app = express()
var compiler = webpack(config)
app.use(
require('webpack-dev-middleware')(compiler, {
publicPath: config.output.publicPath
})
)
app.use(require('webpack-hot-middleware')(compiler, {
heartbeat: 10 * 1000
}))
app.get('*', function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'))
})
const PORT = 8080
app.listen(PORT, function(err) {
if (err) {
return console.error(err)
}
console.log(`Listening at http://localhost:${PORT}/`)
})
webpack.config.js
const path = require('path')
const webpack = require('webpack')
module.exports = {
mode: 'development',
entry: [
'react-hot-loader/patch',
'webpack-hot-middleware/client?path=http://localhost:8080/__webpack_hmr',
'babel-polyfill',
'./src/index.js'
],
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/dist/',
filename: 'bundle.js'
},
target: 'electron-main',
plugins: [ new webpack.HotModuleReplacementPlugin(), new webpack.ExternalsPlugin('commonjs', ['electron']) ],
module: {
rules: [
{
test: /\.(js|jsx)$/, // include .js files
exclude: /node_modules/, // exclude any and all files in the node_modules folder
loader: require.resolve('babel-loader'),
include: path.join(__dirname, 'src')
},
{
test: /\.css$/,
use: [{loader: 'style-loader'}, {loader: 'css-loader'}]
}
]
},
externals: ['electron', 'fs']
}
src/index.js
import React from 'react'
import ReactDOM from "react-dom"
import {AppContainer} from 'react-hot-loader'
import App from './app'
const renderApp = Component => {
ReactDOM.render(
<AppContainer>
<App />
</AppContainer>,
document.getElementById("root")
)
}
renderApp(App)
if (module.hot) {
module.hot.accept('./app.js', () => {
const nextRootContainer = require('./app').default
renderApp(nextRootContainer)
})
}
.babelrc
{
"presets": ["#babel/preset-env", "#babel/preset-react", "#babel/preset-flow"],
"plugins": [
["transform-class-properties", { "loose": true }],
"react-hot-loader/babel"
]
}
any suggestions welcome!!
I have deployed a React app to Heroku. It works fine and all, but whenever I refresh a page that it's not the index ('/'), I keep getting an error: Cannot GET /project/post1.
I have no idea why this is happenning. I configured my express server to serve my static files on all routes, but its not working.
My file structure looks something like this:
-dist
- bundle.js
- index.html
-server.js
This is my server.js file:
var express = require('express');
var path = require('path');
var app = express();
var isProduction = process.env.NODE_ENV === 'production';
var port = isProduction ? process.env.PORT : 3000;
var publicPath = path.resolve(__dirname, './dist');
app.use(express.static(publicPath));
app.get('*', function(request, response) {
response.sendFile(path.join(publicPath))
});
// And run the server
app.listen(port, function () {
console.log('Server running on port ' + port);
});
This is my webpack.prod.config file:
var webpack = require('webpack');
module.exports = {
entry: {
main: './src/index.js'
},
resolve: {
extensions: ['', '.js', '.jsx']
},
output: {
path: __dirname + '/dist',
publicPath: '/dist/',
filename: 'bundle.js'
},
module: {
loaders: [{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'react-hot!babel'
},
{
test: /\.scss$/,
loader: 'style!css!sass'
}]
},
plugins: [
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': '"production"'
}
})
]
};
I call my bundle.js file in the index.html like this:
<body>
<div id="app"></div>
<script src="/bundle.js"></script>
</body>
Your routing happens on the client, not the server. Express doesn't know what it should do on a GET request on /project/post1.
So we send all requests to the client, where you have react-router running. We can do that by configuring a fallback in the server.js file, for example like this:
import fallback from 'express-history-api-fallback';
import express from 'express';
import http from 'http';
// Set up express
const app = express();
const server = http.createServer(app);
const root = `${__dirname}`;
// History Fallback for express
app.use(express.static(root));
app.use(fallback('index.html', { root }));
// Listen
server.listen(8080, '0.0.0.0');
I'm trying to setup hot module reloading in a react/typescript (with TSX) environment. I have used the react/redux real-world example as a model in getting things going, and this is what I have so far:
server.js
var webpack = require('webpack')
var webpackDevMiddleware = require('webpack-dev-middleware')
var webpackHotMiddleware = require('webpack-hot-middleware')
var config = require('./webpack.config')
var app = new (require('express'))()
var port = 3000
var compiler = webpack(config)
app.use(webpackDevMiddleware(compiler, { noInfo: true, publicPath: config.output.publicPath }))
app.use(webpackHotMiddleware(compiler))
app.use(function(req, res) {
res.sendFile(__dirname + '/index.html')
})
app.listen(port, function(error) {
if (error) {
console.error(error)
} else {
console.info("==> 🌎 Listening on port %s. Open up http://localhost:%s/ in your browser.", port, port)
}
})
webpack.config.js
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
'webpack-hot-middleware/client',
path.resolve('./src/index.tsx'),
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({ template: './index.html' })
],
module: {
loaders: [
{ test: /\.tsx?$/, loader: 'ts-loader' }
]
},
resolve: {
extensions: ['', '.ts', '.tsx', '.js', '.json']
},
}
index.tsx
import * as React from 'react';
import { render } from 'react-dom';
import Root from './containers/root';
render(
<Root />,
document.getElementById('root')
);
containers/root.tsx
import * as React from 'react';
export default class Root extends React.Component<void, void> {
render(): JSX.Element {
return (
<p>boom pow</p>
);
}
}
Changing <p>boom pow</p> to <p>boom boom pow</p> in the root element kicks off this in the javascript console in the browser:
[HMR] bundle rebuilding
client.js?3ac5:126 [HMR] bundle rebuilt in 557ms
process-update.js?e13e:27 [HMR] Checking for updates on the server...
process-update.js?e13e:81 [HMR] The following modules couldn't be hot updated: (Full reload needed)
This is usually because the modules which have changed (and their parents) do not know how to hot reload themselves. See http://webpack.github.io/docs/hot-module-replacement-with-webpack.html for more details.
process-update.js?e13e:89 [HMR] - ./src/containers/root.tsx
process-update.js?e13e:89 [HMR] - ./src/index.tsx
I've stepped through these steps as best I can tell, but am still having no luck.
What am I missing?
The problem, as mentioned by commenters, was missing in my loader - I'm not sure if this had anything to do with it, but I also switched to using babel after typescript - and having typescript compile to ES6. New config below:
var path = require('path')
var webpack = require('webpack')
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: [
'webpack-hot-middleware/client',
path.resolve('./src/index.ts'),
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({ template: path.resolve('./src/index.html') })
],
module: {
loaders: [
{ test: /\.tsx?$/,
loaders: [
'react-hot',
'babel?presets[]=es2015',
'ts-loader'
]
},
{ test: /\.json$/,
loader: 'json'
}
]
},
resolve: {
extensions: ['', '.ts', '.tsx', '.js', '.json']
},
}
if someone still struggles with this see the readme: https://github.com/webpack-contrib/webpack-hot-middleware/blob/master/README.md
This module is only concerned with the mechanisms to connect a browser client to a webpack server & receive updates. It will subscribe to changes from the server and execute those changes using webpack's HMR API. Actually making your application capable of using hot reloading to make seamless changes is out of scope, and usually handled by another library.
webpack-hot-middleware doesn't handle hot reload, you'd need to use react-hot-loader for example