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