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
- The node version must be 14.0
- 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.
- File names that run only on the server end with.s.js
- 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
- Do not write logic that runs only in the browser
BeforeCreate, created
In 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