Hello, I’m 17

SSR specifically refers to front-end frameworks that support running the same applications in Node.js (such as React, Preact, Vue, and Svelte), pre-rendering them to HTML, and finally hydrating them on the client side.

Here are some examples of vuE3 pre-rendering and server-side rendering.

Although this example uses the Hotpack tool, the principles are the same and tool-independent.

The sample project

Hotpack provides built-in support for server-side rendering (SSR). The following example contains an SSR example of Vue3 that can be used as a reference for this guide.

  • Vue3 sample project

Source structure

A typical SSR application should have the following source file structure

Index is a page folder that contains the content needed for the Index page

  • Vue vue components
  • Index. b. Js Client-specific entry B is the first letter of browser
  • Index.html HTML templates
  • Index. s server entry S is the first letter of server

Situational experience

Hotpack can do browser rendering, pre-rendering and server-side rendering, support multi-page, single-page, you can choose

To experience the full functionality, let’s prepare the environment

  1. The node version must be 14.0
  2. Install hotpack and download the VUe3 SSR sample project
npm install -g hotpack
git clone https://github.com/duhongwei/hotpack-tpl-vue3.git my-app
cd my-app/main
npm install
Copy the code

When the environment is ready, make sure to execute subsequent commands in the main directory of the my-app project

In the Hotpack project there is no difference between multiple pages and single pages, single pages just add routing on top of multiple pages. Let’s start with simple pages

Multi-page browser rendering

hotpack dev
Copy the code

Hotpack dev launches the development environment, using port 3000 by default

Hotpack dev -p 3001 specifies port 3001

The default command for hotpack is dev so hotpack dev can also be written as hotpack

Open the browser and enter the url localhost:3000. The following information is displayed

Right-click on the page and select Show page source code. The only div on the page is empty. The content is filled by the browser request to JS

<div id='app' pre-ssr></div>
Copy the code

Pre-ssr means you can use pre-render. But it hasn’t worked yet.

Multi-page pre-render

Unlike server rendering, which compiles HTML instantaneously, pre-rendering only generates a specific few static pages for a specific route at build time.

In the development environment, even with the pre-SSR tag, pre-rendering is not turned on (the development environment configuration file is generally configured not to turn on, because pre-rendering is not required when we develop the page). It is easy to enable pre-rendering in the development environment

hotpack dev -r
Copy the code

The default is 3000 localhost:3000. When you open the page, right click on the page, and select Show page source we can clearly see that the page has been rendered.

<div id='app'><div class="index"><h1>Hotpack Vue3 Multi Page Egxample</h1>.Copy the code

Vue3, unlike VUe2, does not have a render tag on a div

Multi-page server rendering

Unlike pre-rendering, server-side rendering compiles and generates HTML from time to time, rendering pages in real time based on paths and data.

Open the page/index/index. HTML

<div id='app' pre-ssr ></div>
Copy the code

Change the pre-SSR to SSR

<div id='app' ssr ></div>
Copy the code

SSR means you can use server-side rendering. In the development environment, even with SSR markers, server rendering is not turned on for the same reason as pre-rendering. The development environment defaults to browser rendering, so that the development efficiency is higher. Add -r to the command line to enable server rendering

hotpack dev -r
Copy the code

The default port is 3000 and localhost:3000. Right-click the page and choose Show the source code

<div id='app' ssr></div>
Copy the code

An empty div with server rendering enabled.

In fact, it is true, because the current server is the server of Hotpack, not the server,hotpack server does not have the ability to compile data at any time. In the development environment, the compiled files are sent to the dev directory. To avoid interference, we can copy the dev directory to the upper level. We can see the effect here

cp -r dev .. /cd ../dev
npm install
node index.js
Copy the code

Check the source file. It’s already rendered.

<div id='app'><div class="index"><h1>Hotpack Vue3 Multi Page Egxample</h1>...
Copy the code

Can you compile it in real time? Of course you can.

Just…

To simplify the project, the data is now fixed and returned directly in API functions. So you can’t see the effect of real-time compilation. If you’re interested, I’ll write another example of asking for real data at all times.

After the multi-page experience, let’s experience the single page

Single-page browser rendering

Open a browser input url localhost: 3000 / single. HTML according to the following content

Viewing source files

<div id='app' ssr></div>
Copy the code

– Server rendering is not performed, for the same reason as pre-rendering, the development environment needs to be enabled with -r, and copy to the upper directory to see the effect

hotpack dev -rs cp -r dev .. / cd .. /dev npm install node index.jsCopy the code

The hotpack dev-s-s parameter prevents server startup in the development environment

Look at the original file. The content has been rendered on the server.

Situational logic

Browser rendering

The browser render entry is in index.b.js

import './index.html=>index.html'
Copy the code

The index. HTML file in the current directory is converted to the /index. HTML web directory. The/is omitted because the path is based on the web root directory.

Multi-page browser rendering

See page/index/index. B.j s

if (window.__state__) {
  store.initState = window.__state__
}
else {
  store.dispatch('init')}Copy the code

Initialize data. If prerendered or rendered by the server, the initialized data is saved in window._state and sent to the browser along with the page. Client hydrating.

Multiple pages are simple and do not require routing.

Store.dispatch (‘user’) is used for comparison with store.dispatch(‘init’). Multiple pages of initialization data are expected, so they are processed together. Not all data is suitable for synchronous use, and asynchronous data can be requested separately.

Single-page browser rendering

A single page feels like just one more route, but it adds a lot of complexity. If window._state has data,

if (window.__state__) {
  storeInfo.state = window.__state__
}
Copy the code

If there is no window._state, it is not possible to send a store.dispatch(‘init’) to complete the process. A single page is routed by the client and the routing determines what data is needed. One idea is to get the data directly from the routing information, but it is better to put the method of getting the data in a module.

page/single/vue/index

export default {
  name: 'index'.ssr(store) {
    return store.dispatch('index')},...Copy the code

Find all related components according to the route in index.b.js, and then trigger the SSR method in the component one by one

router.beforeResolve((to) => {   
  ...
  to.matched.forEach(record => {
    const components = Object.values(record.components)
    components.forEach(item => {
      if (item.ssr) {
        item.ssr(store)
      }
    })
  })
})
Copy the code

One last thing to note is that if window._state has data, you don’t need to request it again

page/single/js/store.js

 actions: {
    ...
    async index({ commit, state }) {
    
      if (state.index) return state.index

      const data = await getIndex()
      commit('index', data)
      return data
    }
 }
Copy the code

.b. js-ending files run only in the browser

Pre-render and server-side render

Prerendering does not require server-side support and is done by compilation tools. The pre-rendered results are constant. This is great for pages where there is no data, or where the data doesn’t change very often.

The page rendered by the server changes from time to time and is truly dynamic.

Both pre-render and server-side render use index.s.js as the entry point

import './index.html=>index.html'
Copy the code

In addition to specifying the template path conversion, the HTML file is the render entry is index.s.js. Using this declarative way to indicate HTML and JS association is for the sake of flexibility. It doesn’t matter where the HTML template goes in the source code, it doesn’t matter where the JS goes, just do what you want.

Hotpack finds this declaration at compile time and stores the HTML and JS association information for later reference.

Files ending in.s.js are only run on the server

Multi-page pre-render and multi-page server render

export default async function () {
    let store = Vuex.createStore(storeInfo)
    const state = await store.dispatch('init')
    let app = await init(component)
    app.use(store)
    return {
        app,
        state
    }
}
Copy the code

Hotpack will execute this function, which returns the instance app of vue and the initialized data state, named state because the initialized data is the store state.

For pre-rendering, this function is executed every time it is compiled, and for server-side rendering, every request page is rendered.

Service rendering only needs to initialize synchronous data, so there is no store.dispatch(‘user’)

Single-page server rendering

It is also possible to pre-render a single page, but a single page other than the first page is requested asynchronously, so for asynchronous pages, the speed advantage of pre-render is meaningless. Hotpack does not support single-page pre-rendering, but you can pre-render the default home page if you wish.

page/single/index.s.js

In contrast to pre-rendering, server-side rendering passes in a CTX, which contains the url and other information related to the request

export default async function (ctx = {}) {...const url = ctx.originalUrl || '/single'
router.push(url)
...
}
Copy the code

Find the relevant component according to the route, trigger the SSR function in the component, and obtain the relevant data. Different from the browser logic, wait for the data to complete, and then render the content

  let components = null
  router.currentRoute.value.matched.flatMap(record= > {
       components = Object.values(record.components)
  })

  let promiseList = components.map(item= > item.ssr(store, ctx))

  await Promise.all(promiseList)
Copy the code

The entire page can be interpolated to modify content, such as title

   <title>{{{title}}}</title>
Copy the code
 return {
      pageData: {
          title: router.currentRoute.value.meta.title
      },
      app,
      state: store.state
  }
Copy the code

<div id= “app SSR “> Don’t put anything here </div>

Scenario selection

There are pros and cons to different rendering methods.

Browser rendering

The lowest cost, the most common and the default for HotPack.

pre-rendered

The cost is slightly higher and you get a significant speed advantage, which is highly recommended for static pages.

Server side rendering

The cost is highest. Unless necessary, it is not recommended. It’s not just about the cost, it’s also about the ability of the developer to master all kinds of knowledge on the server side.


In an application, some pages are suitable for browser rendering, some are suitable for pre-rendering, some are suitable for server-side rendering, some are suitable for single-page rendering, some are suitable for multi-page rendering. In the HotPack project, various rendering methods and page forms are directly supported, and they are progressive and can be converted to each other at any time. Pre-ssr, SSR markers, configuration files, and command lines can be very flexible for conversion.

The configuration file

The configuration files are added to the.hotpack file in the root directory of the project. There are three files base.js, dev.js, and pro.js, corresponding to the public configuration, development configuration, and publishing configuration

The configuration of pre-render and server-side rendering is very simple. If you just pre-render, SRC is not written.

  render: {
    //optional, server render must be copied to dev(dist) directory when hotpack is compiled
    src: "render".// Required, whether to enable
    enable: false
  },
Copy the code

In dev.js SSR is turned off enable:false. However, the COMMAND line has the highest priority. You can enable SSR on the command line at any time

hotpack dev -r
Copy the code

The configuration and command line can only affect pages marked pre-SSR, SSR.

More Configuration Information

Development practices

The development and testing costs of the three rendering methods are progressively higher. Developing an app with HotPack perfectly aligns cost with experience.

Configuration file: The DEVELOPMENT environment is configured to disable SSR, and the distribution environment is configured to enable SSR.

Development is done entirely as a browser render. After the development is complete, add the pre-render server rendering entry and view the effect through hotpack dev -r. There is no need to add -r in the release environment because it is already enabled in the configuration file. The server will not be launched by default when you publish it. If you do, use the -s parameter hotpack pro -s. The -s parameter in the development and release environments has the opposite effect.

For browser-rendered and pre-rendered pages, you can view them directly. To view server rendered pages, copy the entire directory into a clean environment. Because the published directory needs to be copied to the server, the server is a brand new environment. The default release directory of the development environment is dev, and the default release directory of the development environment is pro. Copy the pro directory to the server when it goes online and run NPM install. The files required by the server are placed in the Render directory. With the basic files included in the sample project, Hotpack will automatically copy the files under Render to dev or pro directories.

/render

conclusion

This article is mainly for you to experience, and may be more detailed later.

Hotpack does not convert code that can only run on the server, and you can follow these rules to avoid environmental problems.

  1. File names that run only on the server end with.s.js
  2. Index.b.js,index.s.js have been isolated from the source. Files that run only on servers are referenced only in index.s.js, and files that run only in browsers are referenced only in index.s.js
  3. Do not write logic that runs only in the browserBeforeCreate, createdIn the method

Finally, you can make logical judgments in your code

// Browser environment
if(typeof global= = ='undefined'){
  ...
}
/ / the node environment
else{... }Copy the code

The common file name is xx.js.

Hotpack’s cache is very powerful, but it can also cause problems. You can use the -c argument to clear the cache. Do not clear the cache unless necessary.

Clear the development environment cache
hotpack dev -c
Clear the release environment cache
hotpack pro -c
Copy the code