At the forefront of
From the previous article we learned what SSR is and how to build an SSR application with VUE-cli3. However, some problems were left unaddressed, that is, the hot update function was not added at the time of development. Should the code be recompiled and packaged every time it is updated? Obviously not very reasonable. Then we will add hot update function for the SSR program.
1. Solution
Json and VUE-SSR -server-bundle.json will be generated after the SSR program is packaged and compiled every time
- vue-ssr-client-manifest.json
It records the configuration information of static resource files
- vue-ssr-server-bundle.json
It mainly records the contents of JS files
Json and vuE-SSR -server-bundle.json files.
From this figure, we know that webPack Dev Server will not be able to get away with hot updates.
Therefore, the solution steps are as follows:
- Start a WebPack Dev Server service that exposes port 8080
- Start a Webpack compiler to compile the webpack configuration file, listen for file changes, and compile in real time to get the latest VUE-SSR-server-bundle. json
- Get the latest vuE-SSR-client-manifest.json from webpack Dev Server
- Json with vue-SSR -server-bundle.json and vue-SSR -client-manifest.json render the HTML page back to the browser
2. Coding implementation
With that in mind, all that’s left is to figure out how to do it in code.
2.1. Start a WebPack Dev Server service
With NPM Run serve, we can quickly build a WebPack Dev server service
npm run serve
Copy the code
2.2. Obtain the WebPack configuration file and compile it
By reading the official document we know webpack configuration file in/node_modules / @ vue/cli – service/webpack config. Js
Const webpackConfig = require(const webpackConfig = require('@vue/cli-service/webpack.config')
Copy the code
2.3. Compile the WebPack configuration file and listen for file changes
// Const serverCompiler = webpack(webpackConfig) const MFS = new MemoryFS( ServerCompiler. OutputFileSystem = MFS / / 3, listening file modification, real time compiled for the latest vue - SSR - server - bundle. Jsonlet bundle
serverCompiler.watch({}, (err, stats) =>{
if (err) {
throw err
}
stats = stats.toJson()
stats.errors.forEach(error => console.error(error) )
stats.warnings.forEach( warn => console.warn(warn) )
const bundlePath = path.join(
webpackConfig.output.path,
'vue-ssr-server-bundle.json'
)
bundle = JSON.parse(mfs.readFileSync(bundlePath,'utf-8'))
console.log('new bundle generated')})Copy the code
2.4. Obtain the latest vuE-SSR -client-manifest.json
// If you are manifest-manifest.json = // If you are manifest-manifest.json = // If you are manifest-manifest.json = // If you are manifest-manifest.json = //'http://localhost:8080/vue-ssr-client-manifest.json')
const clientManifest = clientManifestResp.data
Copy the code
2.5. Final code after combining the core of each step
Install the required libraries
npm install webpack memory-fs concurrently -D
npm install koa-router axios -S
Copy the code
In the root directory of the project, create a new server/dev.ssr
// server/dev.ssr.js
const webpack = require('webpack')
const axios = require('axios')
const MemoryFS = require('memory-fs')
const fs = require('fs')
const path = require('path')
const Router = require('koa-router'// 1, const webpackConfig = require()'@vue/cli-service/webpack.config')
const { createBundleRenderer } = require("vue-server-renderer"); Const serverCompiler = webpack(webpackConfig) const MFS = new MemoryFS() // Specifies the output file to the memory stream ServerCompiler. OutputFileSystem = MFS / / 3, listening file modification, real time compiled for the latest vue - SSR - server - bundle. Jsonlet bundle
serverCompiler.watch({}, (err, stats) =>{
if (err) {
throw err
}
stats = stats.toJson()
stats.errors.forEach(error => console.error(error) )
stats.warnings.forEach( warn => console.warn(warn) )
const bundlePath = path.join(
webpackConfig.output.path,
'vue-ssr-server-bundle.json'
)
bundle = JSON.parse(mfs.readFileSync(bundlePath,'utf-8'))
console.log('new bundle generated'}) // Handle requests const handleRequest = async CTX => {console.log()'path', ctx.path)
if(! bundle) { ctx.body ='Wait for Webpack to complete before accessing before accessing'
return} // 4, manifest.json const clientstresp = await axios.get('http://localhost:8080/vue-ssr-client-manifest.json')
const clientManifest = clientManifestResp.data
const renderer = createBundleRenderer(bundle, {
runInNewContext: false,
template: fs.readFileSync(path.resolve(__dirname, ".. /src/index.temp.html"), "utf-8"),
clientManifest: clientManifest
});
const html = await renderToString(ctx,renderer)
ctx.body = html;
}
function renderToString(context,renderer) {
return new Promise((resolve, reject) => {
renderer.renderToString(context, (err, html) => {
err ? reject(err) : resolve(html);
});
});
}
const router = new Router()
router.get("*", handleRequest);
module.exports = router
Copy the code
Create a new server/ssr.js file with the following code
// server/ssr.js
const Koa = require('koa')
const koaStatic = require("koa-static");
const path = require('path') const resolve = file => path.resolve(__dirname, file); const app = new Koa() const isDev = process.env.NODE_ENV ! = ='production'
const router = isDev ? require('./dev.ssr') : require('./server'Use (router.routes()).use(router.allowedmethods ()) // open directory app.use(koaStatic(resolve)".. /dist")));
const port = process.env.PORT || 3000;
app.listen(port, () => {
console.log(`server started at localhost:${port}`);
});
module.exports = app
Copy the code
Modify package.json to add several execution scripts
// package.json scripts field"dev:serve": "cross-env WEBPACK_TARGET=node node ./server/ssr.js"."dev": "concurrently \"npm run serve\" \"npm run dev:serve\" "
Copy the code
Run the NPM run dev command
npm run dev
Copy the code
Go to localhost:3000 and you’ll see that there’s still a problem.
Static resource files refer to node.js server services, i.e. port 3000, but port 3000 does not have these static resource files, these static resource files are in webpack Dev Server.
So what’s the solution?
- Modify Node Server to proxy requests for these static resources into WebPack Dev Server
- Change the baseUrl of webpack to reference it directly to webpack dev server
Obviously, the second option is easier to implement, so let’s change the baseUrl configuration for WebPack
Modify the vue. Config. Js
// vue.config.js // add a field to webPack Dev server baseUrl: isDev?'http://127.0.0.1:8080' : ' '.Copy the code
Rerun NPM run dev and access localhost:3000
It’s working, so let’s see if we can do a hot update, change a piece of code,
You’ll notice that Node Server recompiles the WebPack configuration file and then looks to see if the browser has updated it
You’ll notice that the browser still hasn’t been able to hot update the content, and when you open F12, you’ll notice this error,
This is a common error that does not allow cross-domains.
Solution:
- Configure WebPack Dev Server to allow cross-domain
// vue. Config. js // add a field devServer: {headers: {'Access-Control-Allow-Origin': The '*'}},Copy the code
Rerun NPM run dev and access localhost:3000
Hot updates are already available.
3, optimize
If you open F12, you can still see the problem
See my Github code for details
2. Modify the automatic restart code of the server
It can be implemented using Nodemon or PM2
4, summarize
Through the previous article through vuE-cli3 to build an SSR application and this article, we built a step by step based on vue-cli3 SSR application, and added the hot update function, in this period also stepped on a lot of pit. But when you finally get there, it’s worth it because it lays the foundation for your growth.
If there is a better way to achieve, welcome to exchange!
If there is something wrong, please point it out!
5, the source code
Vue – CLI-SSR -example welcome star
The public,
Welcome to follow my public account “code development”, share the latest technical information every day. Focus on getting the latest resources