React SSR
This article is mainly about some simple implementations of Webpack and SSR
react + next
Server-side Data Fetching feature
Next implements the function of getting data and rendering HTML on the server side. The benefit is naturally better user experience and seo. The API for getting data is getStaticProps
export async function getServerSideProps({params}) {
const req = await fetch(` http://127.0.0.1/${params.id}.json`);
const date = await req.json();
return {
props: {something: data},
}
}
Copy the code
Next is a framework for react server rendering
Initialize the
Create NPX create – next – app
{“dev”: “next dev”}
routing
[directory name] = route name [directory name] = route name [directory name] = route name [directory name] = route name The react component is essentially a function, so each page should have an export default function as a component of next. If the route is followed by the url params parameter, create a new [id].js under the same path to handle (Dynamic Component).
//[id].js uses next-router to retrieve parameters in the URL
import {useRouter} from 'next/rotuer'
export default function ChildPage() {
const router = useRouter()
const {id} = router.query
return JSX.element;
}
Copy the code
About Webpack handwriting Loader
Loader is a declarative function that converts origin data to JS code for webpack compilation
Initialize the
const path = require('path')
module.exports = {
mode: 'development'.entry: path.join(__dirname, 'src/index.js'),
output: {
filename: 'bundle.js'.path: `${__dirname}/dist`
},
module: {
rules:[
test: /\.js$/,
use: [{
path.resolve(__dirname, './xxx/xxx.js'), // here must be the absolute path, XXX is the file that you want to use for parsing
options: {
str: 'MyLoaderParam' // Loader parameters}}}}]Copy the code
loader.js
Parameter passing
// Expose a function that takes the source code as input
module.exports = function(source) {
{STR: 'MyLoaderParam'}. If it is a complex parameter, loaderUtils can also be used
console.log(this.query)
// There must be a return
return source;
}
Copy the code
Asynchronous event processing, mainly using this.async
module.exports = function(source) {
const result = source;
// handle asynchrony,
const callback = this.async();
// Simulate an asynchrony
setTimeOut(() = >{
const result = source;
// return result; Error will be reported
callback(null, result);
}, 3000)}Copy the code
If multiple loaders are executed in order, add the corresponding configuration in webpack.config < use, note that the order is bottom-up (chain), right to left (compose mode).
Processing path
resolveLoader: {
modules: ['node_modules'.'./loaders']}Copy the code
Node_modules is used first, then./loaders, so use can be configured using loader’s name instead of path.resovle
Webpack also provides some other ways to help write loader, the official documentation address: webpack.docschina.org/concepts/lo…
About Webpack handwritten Plugins
Reference: ‘A webpack plugin is a JavaScript object that has an apply method. This apply method is called by the webpack compiler, giving access to the entire compilation lifecycle.’
Plugins are the soul of Webpack. Now there are various plugins in official and third parties, such as HtmlWebpackPlugin (which can generate HTML when exporting resources to DIST after construction), MiniCssExtractPlugin(extract CSS), etc. Plugin includes apply(), parameters, and compiler
The official sample
const pluginName = 'ConsoleLogOnBuildWebpackPlugin';
class ConsoleLogOnBuildWebpackPlugin {
apply(compiler) {
//hooks run represents a component phase, followed by tap if synchronous, tapAsync if asynchronous, and arrow function arguments with callback
compiler.hooks.run.tap(pluginName, (compilation) = > {
console.log('The webpack build process is starting!!! '); }); }}module.exports = ConsoleLogOnBuildWebpackPlugin;
Copy the code
Hooks API documentation: webpack.js.org/api/compile…
So the infrastructure for writing a Plugin is
class xxxPlugin {
//options are passed parameters
constructor(options){}apply(compiler){}}module.exports = xxxPlugin;
Copy the code
Plugins: [new xxxPlugin({name: ‘name’})]
Use emit as an example to write an asynchronous hook function that emit before generating resources to the output directory
// Add a new file to the dist output directory
apply(compiler) {
compiler.hooks.emit.tapAsync(
"xxxPlugin".(compilation, cb) = > {
//compilation. Assets for the compilation
compilation.assets['new.txt'] = {
source: function(){
return "new.txt's content here."
},
size: funciton(){
//30bytes
return 30; } } cb(); }); }Copy the code
webpack + react-ssr
Ideas:
server:
- Render the component as a string using the renderToString method of the React – DOM
- The route on the server returns the correct template
Client:
- Package components that are appropriate for the server side
Full demo address: github.com/PakoMY/reac…
yarn init -y
yarn add webpack webpack-cli webpack-dev-server -D
Directory new webpack.config.js
const path = require('path')
const HtmlPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'development'.entry: path.join(__dirname, 'src/index.js'),
output: {
filename: 'bundle.js'.path: `${__dirname}/dist`
},
module: {
rules: [{
test: /\.(js|jsx)$/,
loader: 'babel-loader'.exclude: /node_modules/}},plugins: [
new HtmlPlugin({
template: path.join(__dirname, 'src/client/index.html')})],devServer: {
hot: true.port: 3000.overlay: true}},Copy the code
Webpack.server. Config adds libraryTarget to output: webpack.server. Config adds libraryTarget to output: webpack.server. ‘Commonjs2’ configuration, make a conversion that imports output according to commonJS standard mode, otherwise node code will compile error)
yarn add file-loader css-loader babel-loader @babel/core @babel/preset-env @babel/preset-react -D
Create client, server, and shared folders under/SRC
yarn add react react-dom
New root directory. Babelrc
{
"presets": ["@babel/preset-env"."@babel/preset-react"]."plugins": ["react-hot-loader/babel"]}Copy the code
NPM install -g webpack-cli (NPM install -g webpack-cli) You can also go to node_modules/bin and run webpack every time the file changes and then generate a static HTML page in dist. If devServer has a port number, you can run webpack-dev-server.)
yarn add html-webpack
-plugin -D
webpack-dev-server –hot
Yarn add react-hot-loader -d (export default hot(app) needs to be added at the end of app.js)
Package. Json added scripts
"scripts": {
"build:client": "webpack"."dev:client": "webpack-dev-server"
}
Copy the code
server.js
const express = require('express')
const app = express()
/ / can react dom server on the server side rendering component ReactDOMServer. RenderToString (element)
const ReactDOMServer = require('react-dom/server')
ReactDOMServer.renderToString()
const port = process.env.PORT || 5000
app.listen(port, () = > console.log(`server on port `${port}))
Copy the code
How to configure SSR routes in non-next framework