Compare commits

...

10 Commits

Author SHA1 Message Date
fbccf3d9e1 remove test route 2024-04-12 20:46:08 -04:00
c5d7d4b275 express wildcard 2024-04-12 20:44:25 -04:00
fb64977d06 implement react-router 2024-04-12 20:43:08 -04:00
d7e9854e70 remove unused imports 2024-04-12 20:10:19 -04:00
db8e8bfd61 add renderer helper 2024-04-12 20:09:51 -04:00
510f1c81dd use webpack-node-externals in server build 2024-04-12 20:04:31 -04:00
6f3b1e5b3f consolidate dev scripts with npm-run-all 2024-04-12 19:58:26 -04:00
f424937b17 refactor for common webpack config 2024-04-12 19:55:40 -04:00
85a131cd74 exclude public build 2024-04-12 19:55:23 -04:00
6d981c6fdf convert to ES2015 imports 2024-04-12 19:17:44 -04:00
10 changed files with 100 additions and 34 deletions

1
.gitignore vendored
View File

@ -1,3 +1,4 @@
node_modules node_modules
build build
public/bundle.js
package-lock.json package-lock.json

View File

@ -4,8 +4,10 @@
"description": "Server side rendering project", "description": "Server side rendering project",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"dev": "npm-run-all --parallel dev:*",
"dev:server": "nodemon --watch build --exec \"node build/bundle.js\"", "dev:server": "nodemon --watch build --exec \"node build/bundle.js\"",
"dev:build:server": "webpack --config webpack.server.js --watch" "dev:build-server": "webpack --config webpack.server.js --watch",
"dev:build-client": "webpack --config webpack.client.js --watch"
}, },
"author": "", "author": "",
"license": "ISC", "license": "ISC",

11
src/client/Routes.js Normal file
View File

@ -0,0 +1,11 @@
import React from "react";
import { Route } from "react-router-dom";
import Home from "./components/Home";
export default () => {
return (
<div>
<Route exact path="/" component={Home} />
</div>
) ;
};

View File

@ -1,7 +1,12 @@
import React from "react"; // ES2015 module syntax import React from "react"; // ES2015 module syntax
const Home = () => { const Home = () => {
return <div>Home component</div>; return (
<div>
<div>Home component</div>
<button onClick={() => console.log('button clicked')}>Button</button>
</div>
);
}; };
export default Home; export default Home;

11
src/client/index.js Normal file
View File

@ -0,0 +1,11 @@
import React from "react";
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import Routes from './Routes';
ReactDOM.hydrate(
<BrowserRouter>
<Routes />
</BrowserRouter>,
document.querySelector('#root')
);

23
src/helpers/renderer.js Normal file
View File

@ -0,0 +1,23 @@
import React from "react";
import { renderToString } from "react-dom/server";
import { StaticRouter } from "react-router-dom";
import Routes from "../client/Routes";
export default (req) => {
const content = renderToString(
<StaticRouter location={req.path} context={{}}>
<Routes />
</StaticRouter>
);
return `
<!DOCTYPE html>
<html>
<head></head>
<body>
<div id="root">${content}</div>
<script src="bundle.js"></script>
</body>
</html>
`
};

View File

@ -1,13 +1,11 @@
const express = require('express'); // CommonJS module syntax import express from 'express';
const React = require('react'); import renderer from './helpers/renderer';
const renderToString = require('react-dom/server').renderToString;
const Home = require('./client/components/Home').default;
const app = express(); const app = express();
app.get('/', (req, res) => { app.use(express.static('public'));
const content = renderToString(<Home />); app.get('*', (req, res) => {
res.send(renderer(req));
res.send(content);
}); });
app.listen(3000, () => { app.listen(3000, () => {

18
webpack.base.js Normal file
View File

@ -0,0 +1,18 @@
module.exports = {
module: {
rules: [
{
test: /\.js?$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
presets: [
'react',
'stage-0',
['env', { targets: { browsers: ['last 2 versions'] }}]
]
}
}
]
}
}

13
webpack.client.js Normal file
View File

@ -0,0 +1,13 @@
const path = require('path');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.base.js');
const config = {
entry: './src/client/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'public')
}
};
module.exports = merge(baseConfig, config);

View File

@ -1,33 +1,17 @@
const path = require('path'); const path = require('path');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.base.js');
const webpackNodeExternals = require('webpack-node-externals');
module.exports = { const config = {
// Tell webpack that we're building a bundle for Node.js, rather than for the browser
target: 'node', target: 'node',
// Tell webpack the root file of our server application
entry: './src/index.js', entry: './src/index.js',
// Tell webpack where to put the output file that is generated
output: { output: {
filename: 'bundle.js', filename: 'bundle.js',
path: path.resolve(__dirname, 'build') path: path.resolve(__dirname, 'build')
}, },
// Tell webpack to run babel on every file it runs through externals: [webpackNodeExternals()]
module: {
rules: [
{
test: /\.js?$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
presets: [
'react',
'stage-0',
['env', { targets: { browsers: ['last 2 versions'] }}]
]
}
}
]
}
}; };
module.exports = merge(baseConfig, config);