Introduction to the

Speed portal:Small Demo based on VUE-CLI4.0 +Typescript+SSR

Net effect: access, which returns HTML fragments and separates vUE dependencies from chunks

Vue SSR Demo

As of vue3, the previous build directory is no longer in use. If you want to change the webpack configuration, you can only create a new vue.config.js file in the root directory. For specific modification, please refer to vuE-CLI2.+ used in the official website of VUe-CLI4.+, this time I directly upgraded to VUe-cli4

Have been implemented:

  • Project structures,
  • Local SSR Development Environment (KOA)
  • Data prefetch using Vuex (demo deleted this part)
  • Package chunk separation optimization
  • Jenkins + Docker continuous integration and deployment
  • Integration into back-end projects (egg.js)

The main command

$ npm install   # install dependencies
$ npm run dev   # Local development├─ 8080 Local Non-SSR Environment $NPM Run Build# window run the package command
$ npm run build:linux   Run the package command in Linux
Copy the code

Project directory

Chrysene ─. Vscode IDE Workspace setup │ ├─ setting. json ├─ distStatic resources (automatically generated)│ └ ─ ─ index. The temp. HTML# SSR template file├ ─ ─ the publicStatic directory, which will be copied to the dist directory as it is packaged├ ─ ─ server# koa service│ ├ ─ ─ index. Js# koa entrance│ └ ─ ─ server. Js# Service logic├ ─ ─ the SRC# Primary source code│ ├ ─ ─ API# request management│ ├─ ├─ ├─ ├─ ├─ exercises# resources│ │ └ ─ ─... │ ├ ─ ─ the plugins# plug-in
│   │   └── ......
│   ├── utils # global methods, etc
│   │   └── ......
│   ├── views # page/view│ │ └ ─ ─... │ ├ ─ ─ App. Vue# entrance Vue│ ├ ─ ─ entry - client. Ts# Client entry│ ├ ─ ─ entry - server. TsServer entry│ ├ ─ ─ the main# Public entrance│ ├ ─ ─ the router. The index. The ts# Route configuration│ ├ ─ ─ store. Index. Ts# Vuex configuration│ ├ ─ ─ vue - shim. Which s# TS module declaration└ ─ ─ browserslistrc# Browser Settings└ ─ ─. Eslintrc. Js# eslintrc set└ ─ ─ gitignore# git to ignore└ ─ ─ Babel. Config. Js# Babel configuration└ ─ ─ Jenkinsfile# Jenkins configuration└ ─ ─ package - lock. Json# Version lock└ ─ ─ package. Json# Project dependencies└ ─ ─ tsconfig. Json# ts configuration file└ ─ ─ vue. Config. Js# webPack configuration file
Copy the code

Webpack configuration file parsing

  1. Turn off CSS Separation
extract: false// We haven't isolated CSS yet, we are tryingCopy the code
  1. Local SSR construction
When webpack-dev-server runs the local service, it will make a packet and hot update. Therefore, the idea is to start a node service again, read and listen to the packaged chunk file for SSR operation. There are two points here - set webpack-dev-serve to allow cross-domain headers: {'Access-Control-Allow-Origin': The '*'}, - set publicPath // add port prefix to access static resources, production environment because it is integrated into the backend project Settings and path OK process.env.node_env! = ='production' ? 'http://localhost:8080' : '/'.Copy the code
  1. Separating chunks reduces packaging volume
Externals: // Externals can be separated to reduce the size of the packaged chunk. Process.env.node_env ==='production' && !TARGET_NODE
  ? {
      vue: 'Vue',
    }
  : undefined,
Copy the code
  1. Injecting version information
new webpack.DefinePlugin({
  'process.env.NODE_ENV': `"${process.env.NODE_ENV || 'development'}"', // note the need to use double quotation marks}),Copy the code
  1. Close the splitChunks
chainWebpack: (config) => {
  config.optimization.splitChunks(undefined);
},
Copy the code

Basic SSR construction

  1. Public entrance Main.ts
// To prevent singleton contamination, export a factory functionexport function createApp(): any {
  const router = createRouter();
  const store = createStore();
  const app = new Vue({
    router,
    store,
    render: (h) => h(App),
  });
  return { app, router, store };
}
Copy the code
  1. Client entry-client.ts
Const {app, router} = createApp(); router.onReady(() => { app.$mount('#app');
});
Copy the code
  1. Server entry-server.ts
404 import {createApp} from if there is no match 404 import {createApp} from'./main';
export default (context: any) =>
  new Promise((resolve, reject) => {
    const { app, router } = createApp();
    router.push(context.url);
    router.onReady(() => {
      const matchedComponents = router.getMatchedComponents();
      if(! matchedComponents.length) {return reject({
          code: 404,
        });
      }
      resolve(app);
    }, reject);
});
Copy the code

4 routing router. Index. Ts

// Make sure that the mode is changedhistory, the routing request can go to the back endexport function createRouter() {
  return new Router({
    mode: 'history',
    routes: [
      {
        path: '/',
        name: 'Home',
        component: () => import(/* webpackChunkName: "Home"* /'./views/Home.vue'),
      },
      {
        path: '/about',
        name: 'About',
        component: () => import(/* webpackChunkName: "about"* /'./views/About.vue'),},]}); }Copy the code

5 Do not perform DOM operations before component mounted hooks, because the server will execute these hooks

6 Implement local SSR

- Reads the chunk packaged by web-dev-server and listens in real time. - When the chunk changes, use'vue-server-renderer'RenderToString, rendered as an HTML stringCopy the code

7 Interface forwarding failed in the local SSR environment

// Although devServer proxy can be configured, the SSR environment is under another Node port, and the interface needs to be forwarded - the interface is standardized, and the requests of the interface class are added'/api'The prefix -koa server.js is used to request the matched interface class'http-proxy-middleware'and'koa2-connect'Interface ForwardingCopy the code

reference

Learn Vue SSR in five steps