├── .vscode └── settings.json ├── SSR-3 ├── .vscode │ └── settings.json ├── build │ ├── utils.js │ ├── webpack.base.js │ ├── webpack.client.js │ └── webpack.server.js ├── babel.config.json ├── public │ ├── index.html │ └── index.ssr.html ├── dist │ ├── client.bundle.js.LICENSE.txt │ ├── server.bundle.js.LICENSE.txt │ ├── index.html │ └── index.ssr.html ├── src │ ├── client-entry.js │ ├── components │ │ ├── Foo.vue │ │ └── Bar.vue │ ├── main.js │ ├── router.js │ ├── App.vue │ ├── store.js │ └── server.entry.js ├── package.json ├── server.js └── 笔记 ├── .gitignore ├── SSR-1 ├── build │ ├── utils.js │ ├── webpack.base.js │ ├── webpack.client.js │ └── webpack.server.js ├── src │ ├── client-entry.js │ ├── server.entry.js │ ├── main.js │ ├── components │ │ ├── Foo.vue │ │ └── Bar.vue │ └── App.vue ├── dist │ ├── client.bundle.js.LICENSE.txt │ ├── server.bundle.js.LICENSE.txt │ ├── index.html │ ├── index.ssr.html │ └── server.bundle.js ├── babel.config.json ├── public │ ├── index.html │ └── index.ssr.html ├── 笔记 ├── package.json └── server.js ├── SSR-2-ERR ├── build │ ├── utils.js │ ├── webpack.base.js │ ├── webpack.client.js │ └── webpack.server.js ├── src │ ├── client-entry.js │ ├── server.entry.js │ ├── main.js │ ├── components │ │ ├── Foo.vue │ │ └── Bar.vue │ └── App.vue ├── dist │ ├── client.bundle.js.LICENSE.txt │ ├── server.bundle.js.LICENSE.txt │ ├── index.ssr.html │ ├── index.html │ └── vue-ssr-client-manifest.json ├── babel.config.json ├── public │ ├── index.html │ └── index.ssr.html ├── package.json ├── 笔记 └── server.js ├── 单页面配置 ├── dist │ ├── bundle.js.LICENSE.txt │ ├── index.html │ └── bundle.js ├── babel.config.json ├── src │ ├── main.js │ ├── components │ │ ├── Bar.vue │ │ └── Foo.vue │ └── App.vue ├── public │ └── index.html ├── template.html ├── 笔记 ├── server.js ├── package.json └── webpack.config.js ├── 基本的服务端渲染 ├── template.html ├── package.json ├── server.js └── package-lock.json └── README.md /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true 3 | } -------------------------------------------------------------------------------- /SSR-3/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "git.ignoreLimitWarning": true 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode 3 | /单页面配置/node_modules 4 | /SSR-2-ERR/node_modules/ 5 | /SSR-3/node_modules/ 6 | -------------------------------------------------------------------------------- /SSR-1/build/utils.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | exports.resolve = dir => { 3 | return path.resolve(__dirname, dir); 4 | }; 5 | -------------------------------------------------------------------------------- /SSR-3/build/utils.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | exports.resolve = dir => { 3 | return path.resolve(__dirname, dir); 4 | }; 5 | -------------------------------------------------------------------------------- /SSR-1/src/client-entry.js: -------------------------------------------------------------------------------- 1 | // 客户端打包 2 | import createApp from "./main"; 3 | const { app } = createApp(); //执行导出的函数 4 | app.$mount("#app"); 5 | -------------------------------------------------------------------------------- /SSR-2-ERR/build/utils.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | exports.resolve = dir => { 3 | return path.resolve(__dirname, dir); 4 | }; 5 | -------------------------------------------------------------------------------- /单页面配置/dist/bundle.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vue.js v2.6.12 3 | * (c) 2014-2020 Evan You 4 | * Released under the MIT License. 5 | */ 6 | -------------------------------------------------------------------------------- /SSR-1/dist/client.bundle.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vue.js v2.6.12 3 | * (c) 2014-2020 Evan You 4 | * Released under the MIT License. 5 | */ 6 | -------------------------------------------------------------------------------- /SSR-1/dist/server.bundle.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vue.js v2.6.12 3 | * (c) 2014-2020 Evan You 4 | * Released under the MIT License. 5 | */ 6 | -------------------------------------------------------------------------------- /SSR-2-ERR/src/client-entry.js: -------------------------------------------------------------------------------- 1 | // 客户端打包 2 | import createApp from "./main"; 3 | const { app } = createApp(); //执行导出的函数 4 | app.$mount("#app"); 5 | -------------------------------------------------------------------------------- /SSR-2-ERR/dist/client.bundle.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vue.js v2.6.12 3 | * (c) 2014-2020 Evan You 4 | * Released under the MIT License. 5 | */ 6 | -------------------------------------------------------------------------------- /SSR-2-ERR/dist/server.bundle.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * Vue.js v2.6.12 3 | * (c) 2014-2020 Evan You 4 | * Released under the MIT License. 5 | */ 6 | -------------------------------------------------------------------------------- /SSR-1/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@babel/plugin-transform-runtime" 4 | ], 5 | "presets": [ 6 | "@babel/preset-env" 7 | ] 8 | } -------------------------------------------------------------------------------- /SSR-3/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@babel/plugin-transform-runtime" 4 | ], 5 | "presets": [ 6 | "@babel/preset-env" 7 | ] 8 | } -------------------------------------------------------------------------------- /单页面配置/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@babel/plugin-transform-runtime" 4 | ], 5 | "presets": [ 6 | "@babel/preset-env" 7 | ] 8 | } -------------------------------------------------------------------------------- /SSR-2-ERR/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "plugins": [ 3 | "@babel/plugin-transform-runtime" 4 | ], 5 | "presets": [ 6 | "@babel/preset-env" 7 | ] 8 | } -------------------------------------------------------------------------------- /单页面配置/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import App from "./App"; 3 | const vm = new Vue({ 4 | el: "#app", 5 | data: {}, 6 | render: h => h(App) 7 | }); 8 | -------------------------------------------------------------------------------- /SSR-2-ERR/dist/index.ssr.html: -------------------------------------------------------------------------------- 1 | {{title}} -------------------------------------------------------------------------------- /SSR-1/src/server.entry.js: -------------------------------------------------------------------------------- 1 | // 服务端打包 2 | import createApp from "./main"; 3 | export default () => { 4 | // 服务端需要调用当前这个文件 去产生一个vue实例 5 | const { app } = createApp(); 6 | return app; //拿这个实例去服务端渲染结果 7 | }; 8 | // 服务端配置好后 【打包后】给node来使用 -------------------------------------------------------------------------------- /SSR-2-ERR/src/server.entry.js: -------------------------------------------------------------------------------- 1 | // 服务端打包 2 | import createApp from "./main"; 3 | export default () => { 4 | // 服务端需要调用当前这个文件 去产生一个vue实例 5 | const { app } = createApp(); 6 | return app; //拿这个实例去服务端渲染结果 7 | }; 8 | // 服务端配置好后 【打包后】给node来使用 -------------------------------------------------------------------------------- /SSR-1/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import App from "./App"; 3 | // 客户端和服务端需要区分开 服务端渲染 每个人都应该有一个自己的vue实例 4 | export default () => { 5 | const app = new Vue({ 6 | render: h => h(App) 7 | }); 8 | return { app }; 9 | }; 10 | -------------------------------------------------------------------------------- /SSR-1/dist/index.html: -------------------------------------------------------------------------------- 1 | index
-------------------------------------------------------------------------------- /SSR-2-ERR/dist/index.html: -------------------------------------------------------------------------------- 1 | index
-------------------------------------------------------------------------------- /SSR-2-ERR/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import App from "./App"; 3 | // 客户端和服务端需要区分开 服务端渲染 每个人都应该有一个自己的vue实例 4 | export default () => { 5 | const app = new Vue({ 6 | router, 7 | render: h => h(App) 8 | }); 9 | return { app }; 10 | }; 11 | -------------------------------------------------------------------------------- /单页面配置/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Document 7 | 8 | 9 |
10 | 11 | -------------------------------------------------------------------------------- /单页面配置/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{title}} 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /基本的服务端渲染/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{title}} 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /SSR-1/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= htmlWebpackPlugin.options.title %> 7 | 8 | 9 |
10 | 11 | -------------------------------------------------------------------------------- /SSR-2-ERR/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= htmlWebpackPlugin.options.title %> 7 | 8 | 9 |
10 | 11 | -------------------------------------------------------------------------------- /SSR-3/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= htmlWebpackPlugin.options.title %> 7 | 8 | 9 |
10 | 11 | -------------------------------------------------------------------------------- /SSR-3/dist/client.bundle.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * vue-router v3.4.7 3 | * (c) 2020 Evan You 4 | * @license MIT 5 | */ 6 | 7 | /*! 8 | * Vue.js v2.6.12 9 | * (c) 2014-2020 Evan You 10 | * Released under the MIT License. 11 | */ 12 | 13 | /*! 14 | * vuex v3.5.1 15 | * (c) 2020 Evan You 16 | * @license MIT 17 | */ 18 | -------------------------------------------------------------------------------- /SSR-3/dist/server.bundle.js.LICENSE.txt: -------------------------------------------------------------------------------- 1 | /*! 2 | * vue-router v3.4.7 3 | * (c) 2020 Evan You 4 | * @license MIT 5 | */ 6 | 7 | /*! 8 | * Vue.js v2.6.12 9 | * (c) 2014-2020 Evan You 10 | * Released under the MIT License. 11 | */ 12 | 13 | /*! 14 | * vuex v3.5.1 15 | * (c) 2020 Evan You 16 | * @license MIT 17 | */ 18 | -------------------------------------------------------------------------------- /SSR-1/public/index.ssr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /SSR-3/public/index.ssr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /SSR-2-ERR/public/index.ssr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /单页面配置/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SSR-3/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | index 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /单页面配置/src/components/Bar.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 17 | 18 | 20 | -------------------------------------------------------------------------------- /单页面配置/src/components/Foo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 17 | 18 | 20 | -------------------------------------------------------------------------------- /SSR-1/dist/index.ssr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{title}} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SSR-3/dist/index.ssr.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{title}} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SSR-1/src/components/Foo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 17 | 18 | 26 | -------------------------------------------------------------------------------- /SSR-3/src/client-entry.js: -------------------------------------------------------------------------------- 1 | // 客户端打包 2 | import createApp from "./main"; 3 | const { app, store } = createApp(); //执行导出的函数 4 | 5 | // 浏览器执行的时候需要将服务端设置的最新状态,替换掉客户端的状态。 6 | if (typeof window !== "undefined" && window.__INITIAL_STATE__) { 7 | // 用服务端的数据替换 变成当前最新的状态 8 | // 浏览器中的状态就会变成服务器最新的状态(因为客户端也注入了store 目的就是让页面能取到值this.$store.state) 9 | store.replaceState(window.__INITIAL_STATE__); 10 | } 11 | 12 | app.$mount("#app"); 13 | -------------------------------------------------------------------------------- /SSR-3/src/components/Foo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 17 | 18 | 26 | -------------------------------------------------------------------------------- /SSR-2-ERR/src/components/Foo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 17 | 18 | 26 | -------------------------------------------------------------------------------- /SSR-3/src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import App from "./App"; 3 | import createRouter from "./router"; 4 | import createStore from "./store"; 5 | // 客户端和服务端需要区分开 服务端渲染 每个人都应该有一个自己的vue实例 6 | export default () => { 7 | const router = createRouter(); //创建新的router实例 8 | const store = createStore(); 9 | const app = new Vue({ 10 | router, 11 | store, 12 | render: h => h(App) 13 | }); 14 | return { app, router, store }; 15 | }; 16 | -------------------------------------------------------------------------------- /单页面配置/src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 26 | 27 | -------------------------------------------------------------------------------- /SSR-1/src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 26 | 27 | -------------------------------------------------------------------------------- /SSR-2-ERR/src/App.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 26 | 27 | -------------------------------------------------------------------------------- /SSR-2-ERR/build/webpack.base.js: -------------------------------------------------------------------------------- 1 | // 基础的webapck配置 服务端和客户端打包都基于它 2 | const VueLoaderPlugin = require("vue-loader/lib/plugin"); 3 | const utils = require("./utils"); 4 | module.exports = { 5 | output: { 6 | filename: "[name].bundle.js", 7 | path: utils.resolve("../dist") 8 | }, 9 | resolve: { 10 | extensions: [".vue", ".js"] 11 | }, 12 | devServer: { 13 | port: Math.floor(Math.random().toFixed(2) * 10000) 14 | }, 15 | 16 | plugins: [new VueLoaderPlugin()] 17 | }; 18 | -------------------------------------------------------------------------------- /SSR-3/src/router.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import Router from "vue-router"; 3 | import Foo from "./components/Foo"; 4 | import Bar from "./components/Bar"; 5 | // 每个服务器创建应用,都应该有一个自己的路由。所以路由也需要写成一个函数 6 | // 每次调用都产生一个路由系统 7 | 8 | Vue.use(Router); 9 | 10 | export default () => { 11 | const router = new Router({ 12 | mode: "history", 13 | // 动态路由必须返回一个promise函数 14 | routes: [{ path: "/", component: Foo }, { path: "/Bar", component: Bar }] 15 | }); 16 | return router; 17 | }; 18 | -------------------------------------------------------------------------------- /SSR-1/src/components/Bar.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 24 | 25 | 30 | -------------------------------------------------------------------------------- /SSR-2-ERR/src/components/Bar.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 24 | 25 | 30 | -------------------------------------------------------------------------------- /基本的服务端渲染/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "base-ssr", 3 | "version": "1.0.0", 4 | "description": "base-ssr", 5 | "main": "main.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "wensiyuan", 10 | "license": "ISC", 11 | "dependencies": { 12 | "koa": "^2.13.0", 13 | "koa-router": "^9.4.0", 14 | "koa-static": "^5.0.0", 15 | "vue": "^2.6.12", 16 | "vue-router": "^3.4.7", 17 | "vue-server-renderer": "^2.6.12", 18 | "vuex": "^3.5.1" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /SSR-1/build/webpack.base.js: -------------------------------------------------------------------------------- 1 | // 基础的webapck配置 服务端和客户端打包都基于它 2 | const VueLoaderPlugin = require("vue-loader/lib/plugin"); 3 | const utils = require("./utils"); 4 | module.exports = { 5 | output: { 6 | filename: "[name].bundle.js", 7 | path: utils.resolve("../dist") 8 | }, 9 | resolve: { 10 | extensions: [".vue", ".js"] 11 | }, 12 | devServer: { 13 | port: Math.floor(Math.random().toFixed(2) * 10000) 14 | }, 15 | 16 | plugins: [new VueLoaderPlugin()] 17 | // devtool: "source-map" // 输出 source-map 方便直接调试 ES6 源码 18 | }; 19 | -------------------------------------------------------------------------------- /SSR-3/build/webpack.base.js: -------------------------------------------------------------------------------- 1 | // 基础的webapck配置 服务端和客户端打包都基于它 2 | const VueLoaderPlugin = require("vue-loader/lib/plugin"); 3 | const utils = require("./utils"); 4 | module.exports = { 5 | output: { 6 | filename: "[name].bundle.js", 7 | path: utils.resolve("../dist") 8 | }, 9 | resolve: { 10 | extensions: [".vue", ".js"] 11 | }, 12 | devServer: { 13 | port: Math.floor(Math.random().toFixed(2) * 10000) 14 | }, 15 | 16 | plugins: [new VueLoaderPlugin()] 17 | // devtool: "source-map" // 输出 source-map 方便直接调试 ES6 源码 18 | }; 19 | -------------------------------------------------------------------------------- /SSR-3/src/App.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 27 | 28 | -------------------------------------------------------------------------------- /SSR-2-ERR/dist/vue-ssr-client-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "publicPath": "auto", 3 | "all": [ 4 | "client.bundle.js" 5 | ], 6 | "initial": [ 7 | "client.bundle.js" 8 | ], 9 | "async": [ 10 | "client.bundle.js" 11 | ], 12 | "modules": { 13 | "3b8cad02": [ 14 | 0 15 | ], 16 | "4a526035": [ 17 | 0 18 | ], 19 | "247d24e8": [ 20 | 0 21 | ], 22 | "51a1d93f": [ 23 | 0 24 | ], 25 | "d7e9791e": [ 26 | 0 27 | ], 28 | "326c9dc8": [ 29 | 0 30 | ], 31 | "8da141ea": [ 32 | 0 33 | ], 34 | "6fbc4fdc": [ 35 | 0 36 | ], 37 | "35b75c20": [ 38 | 0 39 | ] 40 | } 41 | } -------------------------------------------------------------------------------- /单页面配置/笔记: -------------------------------------------------------------------------------- 1 | 一些包 2 | webpack相关 3 | webpack 4 | webpack-cli //命令行解析工具 4.0之前是一起的 4.0之后拆开了 需要安装 5 | webpack-dev-server 6 | 7 | es6转es5 8 | babel-loader //es6=>es5 webpack中接入babel 9 | @babel/core // babel-loader依赖 10 | @babel/preset-env //加入新的语法特性 比如2015年加入的新特性 Env包括所有的新特性 11 | @babel/plugin-transform-runtime 减少冗余代码 默认的polifill属性已经被废除掉了 12 | @babel/runtime @babel/plugin-transform-runtime依赖 13 | 14 | 解析css的包 15 | vue-style-loader //支持服务端渲染 和style-loader功能一样 16 | css-loader 17 | 18 | 处理vue 19 | vue-loader 处理.vue文件 20 | vue-template-loader //处理模板编译 21 | 22 | html-webpack-plugin 23 | webpack-merge 24 | 25 | 26 | ---------------------------- 27 | npx webpack === node_modules/bin/webpack // 这是打包 28 | 29 | 30 | 31 | 关于babel的配置 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /SSR-3/src/components/Bar.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 37 | 38 | 43 | -------------------------------------------------------------------------------- /基本的服务端渲染/server.js: -------------------------------------------------------------------------------- 1 | const Koa = require("koa"); 2 | const Router = require("koa-router"); 3 | const Vue = require("Vue"); 4 | const vueServerRender = require("vue-server-renderer"); 5 | const app = new Koa(); 6 | const router = new Router(); 7 | const vm = new Vue({ 8 | data: { 9 | msg: "hello,ssr" 10 | }, 11 | template: `

{{msg}}

` 12 | }); 13 | 14 | // 创建一个渲染器 为了把vue渲染成字符串 15 | // vueServerRender身上有两个方法 renderToString ,renderToStream 把生成的字符串插入到body中 16 | const render = vueServerRender.createRenderer({ 17 | template: require("fs").readFileSync("./template.html", "utf-8") //把渲染出来的字符串塞到html模板的body中,再由服务端吐出来 模板中必须带有 18 | }); 19 | router.get("/", async ctx => { 20 | // ctx.body='hello,ssr' 21 | ctx.body = await render.renderToString(vm, { title: "base-ssr" }); //返回promise 结果为 '

hello,ssr

' 会把结果塞给template 22 | }); 23 | 24 | app.use(router.routes()); 25 | 26 | app.listen(3004, () => { 27 | console.log("服务器开启成功"); 28 | }); 29 | -------------------------------------------------------------------------------- /单页面配置/server.js: -------------------------------------------------------------------------------- 1 | const Koa = require("koa"); 2 | const Router = require("koa-router"); 3 | const Vue = require("Vue"); 4 | const vueServerRender = require("vue-server-renderer"); 5 | 6 | const app = new Koa(); 7 | const router = new Router(); 8 | const vm = new Vue({ 9 | data: { 10 | msg: "hello,ssr" 11 | }, 12 | template: `

{{msg}}

` 13 | }); 14 | 15 | // 创建一个渲染器 为了把vue渲染成字符串 16 | // vueServerRender身上有两个方法 renderToString ,renderToStream 把生成的字符串插入到body中 17 | const render = vueServerRender.createRenderer({ 18 | template: require("fs").readFileSync("./template.html", "utf-8") //把渲染出来的字符串塞到html模板的body中,再由服务端吐出来 模板中必须带有 19 | }); 20 | router.get("/", async ctx => { 21 | // ctx.body='hello,ssr' 22 | ctx.body = await render.renderToString(vm, { title: "base-ssr" }); //返回promise 结果为 '

hello,ssr

' 会把结果塞给template 23 | }); 24 | 25 | app.use(router.routes()); 26 | 27 | app.listen(300, () => { 28 | console.log("服务器开启成功"); 29 | }); 30 | -------------------------------------------------------------------------------- /SSR-1/build/webpack.client.js: -------------------------------------------------------------------------------- 1 | const Merge = require("webpack-merge"); 2 | const base = require("./webpack.base"); 3 | const HtmlWebpackPlugin = require("html-webpack-plugin"); 4 | const utils = require("./utils"); 5 | module.exports = Merge.merge(base, { 6 | entry: { 7 | client: utils.resolve("./../src/client-entry.js") 8 | }, 9 | module: { 10 | rules: [ 11 | { 12 | test: /\.js$/, 13 | use: { 14 | loader: "babel-loader", 15 | options: { 16 | presets: ["@babel/preset-env"] //新的语法特性 如果需要生效还需要再。babelsrc中配置 17 | } 18 | }, 19 | exclude: /node_modules/ 20 | }, 21 | { 22 | test: /.vue$/, 23 | use: "vue-loader" 24 | }, 25 | { 26 | test: /\.css$/, 27 | use: ["style-loader", "css-loader"] 28 | } 29 | ] 30 | }, 31 | plugins: [ 32 | new HtmlWebpackPlugin({ 33 | title: "index", 34 | filename: "index.html", 35 | template: utils.resolve("./../public/index.html") 36 | }) 37 | ] 38 | }); 39 | -------------------------------------------------------------------------------- /SSR-3/build/webpack.client.js: -------------------------------------------------------------------------------- 1 | const Merge = require("webpack-merge"); 2 | const base = require("./webpack.base"); 3 | const HtmlWebpackPlugin = require("html-webpack-plugin"); 4 | const utils = require("./utils"); 5 | module.exports = Merge.merge(base, { 6 | entry: { 7 | client: utils.resolve("./../src/client-entry.js") 8 | }, 9 | module: { 10 | rules: [ 11 | { 12 | test: /\.js$/, 13 | use: { 14 | loader: "babel-loader", 15 | options: { 16 | presets: ["@babel/preset-env"] //新的语法特性 如果需要生效还需要再。babelsrc中配置 17 | } 18 | }, 19 | exclude: /node_modules/ 20 | }, 21 | { 22 | test: /.vue$/, 23 | use: "vue-loader" 24 | }, 25 | { 26 | test: /\.css$/, 27 | use: ["style-loader", "css-loader"] 28 | } 29 | ] 30 | }, 31 | plugins: [ 32 | new HtmlWebpackPlugin({ 33 | title: "index", 34 | filename: "index.html", 35 | template: utils.resolve("./../public/index.html") 36 | }) 37 | ] 38 | }); 39 | -------------------------------------------------------------------------------- /单页面配置/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-ssr-example", 3 | "version": "1.0.0", 4 | "description": "base-ssr", 5 | "main": "main.js", 6 | "scripts": { 7 | "start": "webpack serve ", 8 | "watch": "webpack --watch" 9 | }, 10 | "author": "wensiyuan", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@babel/runtime": "^7.12.1", 14 | "koa": "^2.13.0", 15 | "koa-router": "^9.4.0", 16 | "koa-static": "^5.0.0", 17 | "vue": "^2.6.12", 18 | "vue-router": "^3.4.7", 19 | "vue-server-renderer": "^2.6.12", 20 | "vuex": "^3.5.1" 21 | }, 22 | "devDependencies": { 23 | "@babel/core": "^7.12.3", 24 | "@babel/plugin-transform-runtime": "^7.12.1", 25 | "@babel/preset-env": "^7.12.1", 26 | "babel-loader": "^8.1.0", 27 | "css-loader": "^5.0.0", 28 | "html-webpack-plugin": "^4.5.0", 29 | "vue-loader": "^15.9.3", 30 | "vue-style-loader": "^4.1.2", 31 | "vue-template-compiler": "^2.6.12", 32 | "vue-template-loader": "^1.1.0", 33 | "webpack": "^5.2.0", 34 | "webpack-cli": "^4.1.0", 35 | "webpack-dev-server": "^3.11.0", 36 | "webpack-merge": "^5.2.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SSR-2-ERR/build/webpack.client.js: -------------------------------------------------------------------------------- 1 | const Merge = require("webpack-merge"); 2 | const base = require("./webpack.base"); 3 | const HtmlWebpackPlugin = require("html-webpack-plugin"); 4 | const utils = require("./utils"); 5 | // 生成一个目录映射 6 | const ClientRenderPlugin = require("vue-server-renderer/client-plugin"); 7 | module.exports = Merge.merge(base, { 8 | entry: { 9 | client: utils.resolve("./../src/client-entry.js") 10 | }, 11 | module: { 12 | rules: [ 13 | { 14 | test: /\.js$/, 15 | use: { 16 | loader: "babel-loader", 17 | options: { 18 | presets: ["@babel/preset-env"] //新的语法特性 如果需要生效还需要再。babelsrc中配置 19 | } 20 | }, 21 | exclude: /node_modules/ 22 | }, 23 | { 24 | test: /.vue$/, 25 | use: "vue-loader" 26 | }, 27 | { 28 | test: /\.css$/, 29 | use: ["style-loader", "css-loader"] 30 | } 31 | ] 32 | }, 33 | plugins: [ 34 | new ClientRenderPlugin(), 35 | new HtmlWebpackPlugin({ 36 | title: "index", 37 | filename: "index.html", 38 | template: utils.resolve("./../public/index.html") 39 | }) 40 | ] 41 | }); 42 | -------------------------------------------------------------------------------- /SSR-1/笔记: -------------------------------------------------------------------------------- 1 | 一些包 2 | webpack相关 3 | webpack 4 | webpack-cli //命令行解析工具 4.0之前是一起的 4.0之后拆开了 需要安装 5 | webpack-dev-server 6 | 7 | es6转es5 8 | babel-loader //es6=>es5 webpack中接入babel 9 | @babel/core // babel-loader依赖 10 | @babel/preset-env //加入新的语法特性 比如2015年加入的新特性 Env包括所有的新特性 11 | @babel/plugin-transform-runtime 减少冗余代码 默认的polifill属性已经被废除掉了 12 | @babel/runtime @babel/plugin-transform-runtime依赖 13 | 14 | 解析css的包 15 | vue-style-loader //支持服务端渲染 和style-loader功能一样 16 | css-loader 17 | 18 | 处理vue 19 | vue-loader 处理.vue文件 20 | vue-template-loader //处理模板编译 21 | 22 | html-webpack-plugin 23 | webpack-merge 24 | 25 | 26 | ---------------------------- 27 | npx webpack === node_modules/bin/webpack // 这是打包 28 | 29 | 30 | 31 | webpack5.0 bug记录 32 | 33 | webpack5.0与webpack-dev-server不兼容 34 | 35 | npm script 需把 "run":"webpack-dev-server --open"改成 36 | "run":"webpack serve" 37 | 38 | 39 | vue-style-loader与css-loader 在服务端打包时style样式不生效问题解决方案 40 | 41 | { 42 | test: /\.css$/, 43 | use: [ 44 | "vue-style-loader", 45 | { 46 | loader: "css-loader", 47 | options: { 48 | esModule: false //默认为true 需要设置为false 49 | } 50 | } 51 | ] 52 | } 53 | 54 | 55 | npm run client:build -- --watch 文件变动执行打包编译 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /单页面配置/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const HtmlWebpackPlugin = require("html-webpack-plugin"); 3 | const VueLoaderPlugin = require("vue-loader/lib/plugin"); 4 | const resolve = dir => { 5 | return path.resolve(__dirname, dir); 6 | }; 7 | module.exports = { 8 | entry: resolve("./src/main.js"), 9 | output: { 10 | filename: "bundle.js", 11 | path: resolve("dist") 12 | }, 13 | resolve: { 14 | extensions: [".vue", ".js"] 15 | }, 16 | devServer: { 17 | contentBase: "./dist" 18 | }, 19 | module: { 20 | rules: [ 21 | { 22 | test: /\.css$/, 23 | use: ["vue-style-loader", "css-loader"] 24 | }, 25 | { 26 | test: /\.js$/, 27 | use: { 28 | loader: "babel-loader", 29 | options: { 30 | presets: ["@babel/preset-env"] //新的语法特性 如果需要生效还需要再。babelsrc中配置 31 | } 32 | }, 33 | exclude: /node_modules/ 34 | }, 35 | { 36 | test: /.vue$/, 37 | use: "vue-loader" 38 | } 39 | ] 40 | }, 41 | plugins: [ 42 | new VueLoaderPlugin(), 43 | new HtmlWebpackPlugin({ 44 | filename: "index.html", 45 | template: resolve("./public/index.html") 46 | }) 47 | ], 48 | devtool: "source-map" // 输出 source-map 方便直接调试 ES6 源码 49 | }; 50 | -------------------------------------------------------------------------------- /SSR-3/src/store.js: -------------------------------------------------------------------------------- 1 | import Vue from "vue"; 2 | import Vuex from "vuex"; 3 | Vue.use(Vuex); 4 | //服务端和客户端都会走此逻辑 服务端先走 客户端再走 5 | export default () => { 6 | let store = new Vuex.Store({ 7 | state: { 8 | username: "song", 9 | email: "123456" 10 | }, 11 | mutations: { 12 | changeName(state) { 13 | state.username = "hello"; 14 | }, 15 | changeEmail(state) { 16 | state.email = "178382039@qq.com"; 17 | } 18 | }, 19 | actions: { 20 | // 此处如果是服务端调用必须返回 promise 否则不生效 因为在service.entry.js的逻辑是Promise.all() 21 | // 自己有里面的所有数据都获取完之后才会渲染app.vue 所以会等待三秒才渲染数据 22 | // 只写setTimeout 不生效 因为setTimeout是异步的,在vuex实例渲染完成后才被调用,此时页面已经被当成字符串渲染到浏览器上了。 23 | changeName({ commit }) { 24 | return new Promise((resolve, reject) => { 25 | setTimeout(() => { 26 | commit("changeName"); 27 | resolve(); 28 | }, 3000); 29 | }); 30 | }, 31 | changeEmail({ commit }) { 32 | setTimeout(() => { 33 | commit("changeEmail"); 34 | }, 2000); 35 | } 36 | } 37 | }); 38 | return store; 39 | }; 40 | 41 | // 解释流程 42 | 43 | // 刷新页面--先执行服务端渲染-执行vuex-把state挂载到window上 44 | // 客户端(client.bundle.js)执行时,通过store.replaceState()把执行的结果替换掉, 客户端也就是指引入的js逻辑比如 mounted(){} 45 | // 那么此时拿到的我就是最新状态 此时我们再去取值那就是设置好的状态了 46 | -------------------------------------------------------------------------------- /SSR-1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-ssr-example", 3 | "version": "1.0.0", 4 | "description": "base-ssr", 5 | "main": "main.js", 6 | "scripts": { 7 | "dev": "webpack serve --config ./build/webpack.client.js --mode development", 8 | "client:build": "webpack --config ./build/webpack.client.js --mode production", 9 | "server:build": "webpack --config ./build/webpack.server.js --mode production" 10 | }, 11 | "author": "wensiyuan", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@babel/runtime": "^7.12.1", 15 | "koa": "^2.13.0", 16 | "koa-router": "^9.4.0", 17 | "koa-static": "^5.0.0", 18 | "vue": "^2.6.12", 19 | "vue-router": "^3.4.7", 20 | "vue-server-renderer": "^2.6.12", 21 | "vuex": "^3.5.1" 22 | }, 23 | "devDependencies": { 24 | "@babel/core": "^7.12.3", 25 | "@babel/plugin-transform-runtime": "^7.12.1", 26 | "@babel/preset-env": "^7.12.1", 27 | "babel-loader": "^8.1.0", 28 | "css-loader": "^5.0.0", 29 | "html-webpack-plugin": "^4.5.0", 30 | "style-loader": "^2.0.0", 31 | "vue-loader": "^15.9.3", 32 | "vue-style-loader": "^4.1.2", 33 | "vue-template-compiler": "^2.6.12", 34 | "vue-template-loader": "^1.1.0", 35 | "webpack": "^5.2.0", 36 | "webpack-cli": "^4.1.0", 37 | "webpack-dev-server": "^3.11.0", 38 | "webpack-merge": "^5.2.0" 39 | } 40 | } -------------------------------------------------------------------------------- /SSR-3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-ssr-example", 3 | "version": "1.0.0", 4 | "description": "base-ssr", 5 | "main": "main.js", 6 | "scripts": { 7 | "dev": "webpack serve --config ./build/webpack.client.js --mode development", 8 | "client:build": "webpack --config ./build/webpack.client.js --mode production", 9 | "server:build": "webpack --config ./build/webpack.server.js --mode production" 10 | }, 11 | "author": "wensiyuan", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@babel/runtime": "^7.12.1", 15 | "koa": "^2.13.0", 16 | "koa-router": "^9.4.0", 17 | "koa-static": "^5.0.0", 18 | "vue": "^2.6.12", 19 | "vue-router": "^3.4.7", 20 | "vue-server-renderer": "^2.6.12", 21 | "vuex": "^3.5.1" 22 | }, 23 | "devDependencies": { 24 | "@babel/core": "^7.12.3", 25 | "@babel/plugin-transform-runtime": "^7.12.1", 26 | "@babel/preset-env": "^7.12.1", 27 | "babel-loader": "^8.1.0", 28 | "css-loader": "^5.0.0", 29 | "html-webpack-plugin": "^4.5.0", 30 | "style-loader": "^2.0.0", 31 | "vue-loader": "^15.9.3", 32 | "vue-style-loader": "^4.1.2", 33 | "vue-template-compiler": "^2.6.12", 34 | "vue-template-loader": "^1.1.0", 35 | "webpack": "^5.2.0", 36 | "webpack-cli": "^4.1.0", 37 | "webpack-dev-server": "^3.11.0", 38 | "webpack-merge": "^5.2.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SSR-2-ERR/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-ssr-example", 3 | "version": "1.0.0", 4 | "description": "base-ssr", 5 | "main": "main.js", 6 | "scripts": { 7 | "dev": "webpack serve --config ./build/webpack.client.js --mode development", 8 | "client:build": "webpack --config ./build/webpack.client.js --mode production", 9 | "server:build": "webpack --config ./build/webpack.server.js --mode production" 10 | }, 11 | "author": "wensiyuan", 12 | "license": "ISC", 13 | "dependencies": { 14 | "@babel/runtime": "^7.12.1", 15 | "koa": "^2.13.0", 16 | "koa-router": "^9.4.0", 17 | "koa-static": "^5.0.0", 18 | "vue": "^2.6.12", 19 | "vue-router": "^3.4.7", 20 | "vue-server-renderer": "^2.6.12", 21 | "vuex": "^3.5.1" 22 | }, 23 | "devDependencies": { 24 | "@babel/core": "^7.12.3", 25 | "@babel/plugin-transform-runtime": "^7.12.1", 26 | "@babel/preset-env": "^7.12.1", 27 | "babel-loader": "^8.1.0", 28 | "css-loader": "^5.0.0", 29 | "html-webpack-plugin": "^4.5.0", 30 | "style-loader": "^2.0.0", 31 | "vue-loader": "^15.9.3", 32 | "vue-style-loader": "^4.1.2", 33 | "vue-template-compiler": "^2.6.12", 34 | "vue-template-loader": "^1.1.0", 35 | "webpack": "^5.2.0", 36 | "webpack-cli": "^4.1.0", 37 | "webpack-dev-server": "^3.11.0", 38 | "webpack-merge": "^5.2.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SSR-1/server.js: -------------------------------------------------------------------------------- 1 | const Koa = require("koa"); 2 | const Router = require("koa-router"); 3 | const static = require("koa-static"); 4 | const vueServerRender = require("vue-server-renderer"); 5 | const fs = require("fs"); 6 | const { pathToFileURL } = require("url"); 7 | const app = new Koa(); 8 | const router = new Router(); 9 | const path = require("path"); 10 | const serverBundle = fs.readFileSync("./dist/server.bundle.js", "utf8"); 11 | const template = fs.readFileSync("./dist/index.ssr.html", "utf8"); 12 | // 渲染打包后的结果 13 | const render = vueServerRender.createBundleRenderer(serverBundle, { 14 | template 15 | }); 16 | 17 | // koa只能用promise 18 | router.get("/", async ctx => { 19 | // 此时打包之后的结果全是字符串,字符串没有任何的事件功能 所以js逻辑不生效(打包之后vue-server-render也会丢弃js逻辑,所以页面中只有css(vue-style-loader的功劳)和html逻辑) 20 | // 所以需要把客户端打包后的结果挂载到模板上,因为客户端代码包含事件逻辑 21 | // 此时需要三个个步骤 1.在模板(dist目录)中先手动引入客户端打包后的结果 (因为js中的事件逻辑不需要被怕成爬取) 22 | // 2.但此时服务器并没有读取此文件,所以需要koa-static静态服务中间件 去dist查找此文件 23 | // 3.需要在App.vue中指定id='app' ,客户端激活 24 | // 这种方法比较笨 25 | 26 | ctx.body = await new Promise((resolve, reject) => { 27 | // 必须写成回调函数的形式否则css样式不生效 28 | render.renderToString( 29 | { 30 | title: "服务" 31 | }, 32 | (err, data) => { 33 | if (err) reject(err); 34 | resolve(data); 35 | } 36 | ); 37 | }); // 返回promise 结果为 '

hello,ssr

' 会把结果塞给template 38 | }); 39 | 40 | app.use(router.routes()); 41 | // koa静态服务中间件 会去dist目录插查找看是否有client.bundle.js 如果有就从服务器中返回此文件 42 | app.use(static(path.resolve(__dirname, "dist"))); 43 | let port = 8003; 44 | app.listen(port, () => { 45 | console.log("服务器开启成功"); 46 | }); 47 | -------------------------------------------------------------------------------- /SSR-2-ERR/笔记: -------------------------------------------------------------------------------- 1 | 一些包 2 | webpack相关 3 | webpack 4 | webpack-cli //命令行解析工具 4.0之前是一起的 4.0之后拆开了 需要安装 5 | webpack-dev-server 6 | 7 | es6转es5 8 | babel-loader //es6=>es5 webpack中接入babel 9 | @babel/core // babel-loader依赖 10 | @babel/preset-env //加入新的语法特性 比如2015年加入的新特性 Env包括所有的新特性 11 | @babel/plugin-transform-runtime 减少冗余代码 默认的polifill属性已经被废除掉了 12 | @babel/runtime @babel/plugin-transform-runtime依赖 13 | 14 | 解析css的包 15 | vue-style-loader //支持服务端渲染 和style-loader功能一样 16 | css-loader 17 | 18 | 处理vue 19 | vue-loader 处理.vue文件 20 | vue-template-loader //处理模板编译 21 | 22 | html-webpack-plugin 23 | webpack-merge 24 | 25 | 26 | ---------------------------- 27 | npx webpack === node_modules/bin/webpack // 这是打包 28 | 29 | 30 | 31 | webpack5.0 bug记录 32 | 33 | 问题一 34 | 35 | webpack5.0与webpack-dev-server不兼容 36 | 37 | npm script 需把 "run":"webpack-dev-server --open"改成 38 | "run":"webpack serve" 39 | 40 | 问题2 41 | 42 | vue-style-loader与css-loader 在服务端打包时style样式不生效问题解决方案 43 | 44 | { 45 | test: /\.css$/, 46 | use: [ 47 | "vue-style-loader", 48 | { 49 | loader: "css-loader", 50 | options: { 51 | esModule: false //默认为true 需要设置为false 52 | } 53 | } 54 | ] 55 | } 56 | 57 | 58 | 问题三 59 | build目录中 webpack.server.js 60 | const ServerRenderPlugin = require("vue-server-renderer/server-plugin") 报错 61 | 62 | 解决方案 修改vue-server-renderer包中的代码 63 | 64 | https://github.com/vuejs/vue/issues/11718#issuecomment-717786088 65 | 66 | 67 | 68 | 问题四 69 | 70 | 使用 const ClientRenderPlugin = require("vue-server-renderer/client-plugin"); 71 | const ServerRenderPlugin = require("vue-server-renderer/server-plugin"); 72 | 自动引入js文件时服务端会报错 展示没有解决办法 需要手动引入js文件 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /SSR-3/src/server.entry.js: -------------------------------------------------------------------------------- 1 | // 服务端打包 2 | import createApp from "./main"; 3 | // 通过server.js文件中的toString传进来的参数 4 | // 服务端会执行此方法 5 | 6 | export default context => { 7 | // // 服务端需要调用当前这个文件 去产生一个vue实例 8 | // const { app, router } = createApp(); 9 | // // context.url 服务端要把对应的路由和此url相匹配 10 | // router.push(context.url); //渲染当前页面对应的路由 11 | // return app; //拿这个实例去服务端渲染结果 12 | 13 | // 为了异步渲染 建议使用promise 服务端renderToString会等待promise执行完成再执行 14 | return new Promise((resolve, reject) => { 15 | // 服务端需要调用当前这个文件 去产生一个vue实例 16 | const { app, router, store } = createApp(); 17 | // context.url 服务端要把对应的路由和此url相匹配 18 | router.push(context.url); //渲染当前页面对应的路由 19 | // 页面跳转成功之后,所有异步组件加载完毕再执行 20 | router.onReady(() => { 21 | // 获取当前跳转匹配到的所有组件,整个都在服务端执行 22 | const match = router.getMatchedComponents(); 23 | if (match.length === 0) { 24 | //会走到renderToString的err中 25 | reject({ code: 404 }); 26 | } 27 | // 有可能匹配多个组件 28 | Promise.all( 29 | match.map(component => { 30 | // 只是在服务端渲染好之后返回出去的 31 | if (component.asyncData) { 32 | // 如果服务端没有asyncData更改状态 是不需要等待的 33 | //asyncData是在服务端调用的。如果当前的路由组件有asyncData函数 就执行此函数。 34 | return component.asyncData(store); 35 | } 36 | }) 37 | ).then(() => { 38 | // Parmise.all()中的方法会改变store中的state 此时数据已经被改变 39 | // 服务器执行完成之后把状态改变了 会在window上生成一个变量 40 | // __INITIAL_STATE__是固定的名字 41 | context.state = store.state; //名字必须为state(规定) 把vuex的状态挂载到上下文中,会将状态挂载到window上 42 | // { 43 | // title: "服务", 44 | // url: ctx.url, 45 | // context:store.state 46 | // }, 47 | resolve(app); 48 | }); 49 | }, reject); 50 | }); 51 | }; 52 | // 服务端配置好后 【打包后】给node来使用 53 | -------------------------------------------------------------------------------- /SSR-1/build/webpack.server.js: -------------------------------------------------------------------------------- 1 | const Merge = require("webpack-merge"); 2 | const base = require("./webpack.base"); 3 | const HtmlWebpackPlugin = require("html-webpack-plugin"); 4 | const utils = require("./utils"); 5 | const { node } = require("webpack"); 6 | module.exports = Merge.merge(base, { 7 | entry: { 8 | server: utils.resolve("./../src/server.entry.js") 9 | }, 10 | target: "node", //打包后的结果给node来使用 node中会使用const path=require('path') 如果不指定为node环境 打包后的结果会包含path模块 11 | output: { 12 | libraryTarget: "commonjs2" //打包后的结果给node来使用 把最终执行的结果放到module.exports上 13 | /** node执行原理 14 | (function(){ 15 | //自己的代码 16 | function(){} 17 | })() 18 | */ 19 | }, 20 | module: { 21 | rules: [ 22 | { 23 | test: /.vue$/, 24 | use: "vue-loader" 25 | // options: { 26 | // // enable CSS extraction 27 | // extractCSS: true 28 | // } 29 | }, 30 | { 31 | test: /\.js$/, 32 | use: { 33 | loader: "babel-loader", 34 | options: { 35 | presets: ["@babel/preset-env"] //新的语法特性 如果需要生效还需要再。babelsrc中配置 36 | } 37 | }, 38 | exclude: /node_modules/ 39 | }, 40 | { 41 | test: /\.css$/, 42 | use: [ 43 | "vue-style-loader", 44 | { 45 | loader: "css-loader", 46 | options: { 47 | esModule: false 48 | } 49 | } 50 | ] 51 | } 52 | ] 53 | }, 54 | plugins: [ 55 | new HtmlWebpackPlugin({ 56 | title: "{{title}}", 57 | minify: { 58 | collapseWhitespace: true, //压缩代码 59 | removeComments: false //不移除注释 60 | }, 61 | filename: "index.ssr.html", 62 | template: utils.resolve("./../public/index.ssr.html"), 63 | excludeChunks: ["server"] //排除在模板中引用打包之后的server.js 64 | }) 65 | ] 66 | }); 67 | -------------------------------------------------------------------------------- /SSR-3/build/webpack.server.js: -------------------------------------------------------------------------------- 1 | const Merge = require("webpack-merge"); 2 | const base = require("./webpack.base"); 3 | const HtmlWebpackPlugin = require("html-webpack-plugin"); 4 | const utils = require("./utils"); 5 | const { node } = require("webpack"); 6 | module.exports = Merge.merge(base, { 7 | entry: { 8 | server: utils.resolve("./../src/server.entry.js") 9 | }, 10 | target: "node", //打包后的结果给node来使用 node中会使用const path=require('path') 如果不指定为node环境 打包后的结果会包含path模块 11 | output: { 12 | libraryTarget: "commonjs2" // 打包后的结果给node来使用 把最终执行的结果放到module.exports上 13 | /** node执行原理 14 | (function(){ 15 | //自己的代码 16 | function(){} 17 | })() 18 | */ 19 | }, 20 | module: { 21 | rules: [ 22 | { 23 | test: /.vue$/, 24 | use: "vue-loader" 25 | // options: { 26 | // // enable CSS extraction 27 | // extractCSS: true 28 | // } 29 | }, 30 | { 31 | test: /\.js$/, 32 | use: { 33 | loader: "babel-loader", 34 | options: { 35 | presets: ["@babel/preset-env"] //新的语法特性 如果需要生效还需要再。babelsrc中配置 36 | } 37 | }, 38 | exclude: /node_modules/ 39 | }, 40 | { 41 | test: /\.css$/, 42 | use: [ 43 | "vue-style-loader", 44 | { 45 | loader: "css-loader", 46 | options: { 47 | esModule: false 48 | } 49 | } 50 | ] 51 | } 52 | ] 53 | }, 54 | plugins: [ 55 | new HtmlWebpackPlugin({ 56 | title: "{{title}}", 57 | minify: { 58 | collapseWhitespace: true, //压缩代码 59 | removeComments: false //不移除注释 60 | }, 61 | filename: "index.ssr.html", 62 | template: utils.resolve("./../public/index.ssr.html"), 63 | excludeChunks: ["server"] //排除在模板中引用打包之后的server.js 64 | }) 65 | ] 66 | }); 67 | -------------------------------------------------------------------------------- /SSR-2-ERR/build/webpack.server.js: -------------------------------------------------------------------------------- 1 | const Merge = require("webpack-merge"); 2 | const base = require("./webpack.base"); 3 | const HtmlWebpackPlugin = require("html-webpack-plugin"); 4 | const utils = require("./utils"); 5 | // 打包出一个文件 指向server.bundle.js 6 | const ServerRenderPlugin = require("vue-server-renderer/server-plugin"); 7 | module.exports = Merge.merge(base, { 8 | entry: { 9 | server: utils.resolve("./../src/server.entry.js") 10 | }, 11 | target: "node", //打包后的结果给node来使用 node中会使用const path=require('path') 如果不指定为node环境 打包后的结果会包含path模块 12 | output: { 13 | libraryTarget: "commonjs2" // 打包后的结果给node来使用 把最终执行的结果放到 module.exports上 14 | /** node执行原理 15 | (function(){ 16 | //自己的代码 17 | function(){} 18 | })() 19 | */ 20 | }, 21 | module: { 22 | rules: [ 23 | { 24 | test: /.vue$/, 25 | use: "vue-loader" 26 | // options: { 27 | // // enable CSS extraction 28 | // extractCSS: true 29 | // } 30 | }, 31 | { 32 | test: /\.js$/, 33 | use: { 34 | loader: "babel-loader", 35 | options: { 36 | presets: ["@babel/preset-env"] //新的语法特性 如果需要生效还需要再。babelsrc中配置 37 | } 38 | }, 39 | exclude: /node_modules/ 40 | }, 41 | { 42 | test: /\.css$/, 43 | use: [ 44 | "vue-style-loader", 45 | { 46 | loader: "css-loader", 47 | options: { 48 | esModule: false 49 | } 50 | } 51 | ] 52 | } 53 | ] 54 | }, 55 | plugins: [ 56 | new ServerRenderPlugin(), 57 | new HtmlWebpackPlugin({ 58 | title: "{{title}}", 59 | minify: { 60 | collapseWhitespace: true, //压缩代码 61 | removeComments: false //不移除注释 62 | }, 63 | filename: "index.ssr.html", 64 | template: utils.resolve("./../public/index.ssr.html"), 65 | excludeChunks: ["server"] // 排除在模板中引用打包之后的server.js 66 | }) 67 | ] 68 | }); 69 | -------------------------------------------------------------------------------- /SSR-2-ERR/server.js: -------------------------------------------------------------------------------- 1 | const Koa = require("koa"); 2 | const Router = require("koa-router"); 3 | const static = require("koa-static"); 4 | const vueServerRender = require("vue-server-renderer"); 5 | const fs = require("fs"); 6 | const { pathToFileURL } = require("url"); 7 | const app = new Koa(); 8 | const router = new Router(); 9 | const path = require("path"); 10 | // 不读取它 而是引入映射文件 交给vue-server-renderer自动出路 11 | // const serverBundle = fs.readFileSync("./dist/server.bundle.js", "utf8"); 12 | // 需要在build目录中配置好webpack plugin 13 | const serverBundle = require("./dist/vue-ssr-server-bundle.json"); // 引入服务端映射文件 14 | const clientManifest = require("./dist/vue-ssr-client-manifest.json"); // 引入客户端映射文件 15 | const template = fs.readFileSync("./dist/index.ssr.html", "utf8"); 16 | // 渲染打包后的结果 让客户端与服务端文件相互关联 17 | // 相当于告诉webpack 服务端打包的时候需要用到manifest.json(客户端的映射文件),然后根据这个映射文件在template模板中自动注入客户端js文件(client.bundle.js) 18 | // 这样就不需要主动去引入客户端打包好的js文件了 19 | const render = vueServerRender.createBundleRenderer(serverBundle, { 20 | template, 21 | clientManifest 22 | }); 23 | 24 | // koa只能用promise 25 | router.get("/", async ctx => { 26 | // 此时打包之后的结果全是字符串,字符串没有任何的事件功能 所以js逻辑不生效(打包之后vue-server-render也会丢弃js逻辑,所以页面中只有css(vue-style-loader的功劳)和html逻辑) 27 | // 所以需要把客户端打包后的结果挂载到模板上,因为客户端代码包含事件逻辑 28 | // 此时需要三个个步骤 1.在模板(dist目录)中先手动引入客户端打包后的结果 (因为js中的事件逻辑不需要被爬虫爬取) 29 | // 2.但此时服务器并没有读取此文件,所以需要 koa-static 静态服务中间件 去dist查找此文件 30 | // 3.需要在App.vue中指定id='app' ,客户端激活 31 | // 这种方法比较笨 32 | 33 | ctx.body = await new Promise((resolve, reject) => { 34 | // 必须写成回调函数的形式否则css样式不生效 35 | render.renderToString( 36 | { 37 | title: "服务" 38 | }, 39 | (err, data) => { 40 | if (err) reject(err); 41 | resolve(data); 42 | } 43 | ); 44 | }); // 返回promise 结果为 '

hello,ssr

' 会把结果塞给 template 45 | }); 46 | 47 | app.use(router.routes()); 48 | // koa静态服务中间件 会去dist目录插查找看是否有client.bundle.js 如果有就从服务器中返回此文件 49 | app.use(static(path.resolve(__dirname, "dist"))); 50 | let port = 8020; 51 | app.listen(port, () => { 52 | console.log("服务器开启成功", `http://localhost:${port}/`); 53 | }); 54 | -------------------------------------------------------------------------------- /SSR-3/server.js: -------------------------------------------------------------------------------- 1 | let port = 8059; 2 | const Koa = require("koa"); 3 | const Router = require("koa-router"); 4 | const static = require("koa-static"); 5 | const vueServerRender = require("vue-server-renderer"); 6 | const fs = require("fs"); 7 | const { pathToFileURL } = require("url"); 8 | const app = new Koa(); 9 | const router = new Router(); 10 | const path = require("path"); 11 | const serverBundle = fs.readFileSync("./dist/server.bundle.js", "utf8"); 12 | const template = fs.readFileSync("./dist/index.ssr.html", "utf8"); 13 | // 渲染打包后的结果 14 | // 此方法会自动去调用client.service.js文件中导出的函数 供rendertostring传参使用 15 | const render = vueServerRender.createBundleRenderer(serverBundle, { 16 | template 17 | }); 18 | 19 | // koa只能用promise 20 | router.get("/", async ctx => { 21 | // 此时打包之后的结果全是字符串,字符串没有任何的事件功能 所以js逻辑不生效(打包之后vue-server-render也会丢弃js逻辑,所以页面中只有css(vue-style-loader的功劳)和html逻辑) 22 | // 所以需要把客户端打包后的结果挂载到模板上,因为客户端代码包含事件逻辑 23 | // 此时需要三个个步骤 1.在模板(dist目录)中先手动引入客户端打包后的结果 (因为js中的事件逻辑不需要被怕成爬取) 24 | // 2.但此时服务器并没有读取此文件,所以需要koa-static静态服务中间件 去dist查找此文件 25 | // 3.需要在App.vue中指定id='app' ,客户端激活 26 | // 这种方法比较笨 27 | 28 | ctx.body = await new Promise((resolve, reject) => { 29 | // 必须写成回调函数的形式否则css样式不生效 30 | render.renderToString( 31 | { 32 | title: "服务", 33 | url: "/" 34 | }, 35 | (err, data) => { 36 | if (err) reject(err); 37 | resolve(data); 38 | } 39 | ); 40 | }); // 返回promise 结果为 '

hello,ssr

' 会把结果塞给template 41 | }); 42 | // 中间件 43 | app.use(router.routes()); 44 | 45 | // koa静态服务中间件 会去dist目录插查找看是否有client.bundle.js 如果有就从服务器中返回此文件 46 | app.use(static(path.resolve(__dirname, "dist"))); 47 | // 中间件 当找不到路由时会走此逻辑 48 | // 如果匹配不到路由就会走此逻辑(当路由不是/时,要跳转到对应的路径,渲染对应的页面) 49 | // 如果服务器没有此路径,会渲染当前的app.vue(首页)文件,在渲染时中又会重新指向/bar路径对应的页面 50 | // 此中间件需要放到最后 51 | app.use(async ctx => { 52 | // 获取到server.entry.js中配置404逻辑 53 | try { 54 | ctx.body = await new Promise((resolve, reject) => { 55 | // 必须写成回调函数的形式否则css样式不生效 56 | render.renderToString( 57 | { 58 | title: "服务", 59 | url: ctx.url //比如当前请求的时/bar 那就把/bar传到server.entry.js中的content 60 | }, 61 | (err, data) => { 62 | if (err) reject(err); 63 | resolve(data); 64 | } 65 | ); 66 | }); 67 | } catch (error) { 68 | ctx.body = "404"; 69 | } 70 | }); 71 | app.listen(port, () => { 72 | console.log("服务器开启成功", `http://localhost:${port}/`); 73 | }); 74 | 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## 使用 3 | 4 | - 在SSR-3目录中 npm install 安装依赖 5 | - 打包服务端 npm run server:build 6 | - 打包客户端 npm run client:build 7 | 8 | - 在dist目录index.ssr.html中引入客户端代码`` 9 | 10 | - 执行服务端脚本 `node server.js` 11 | 12 | # webpack5.0尝鲜 SSR+Vue+Koa+vue-router+vuex【排坑记录】 13 | 14 | ![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0eb6c4b857fe413bb2038e6601722155~tplv-k3u1fbpfcp-watermark.image) 15 | 16 | ## 一些包 17 | 18 | ### webpack相关 19 | 20 | - webpack 21 | - webpack-cli 命令行解析工具 4.0之前是一起的 4.0之后拆开了 需要安装 22 | - webpack-dev-server 23 | - html-webpack-plugin 24 | - webpack-merge 25 | 26 | ### es6转es5 27 | 28 | - babel-loader es6=>es5 webpack中接入babel 29 | - @babel/core babel-loader依赖 30 | - @babel/preset-env 加入新的语法特性 比如2015年加入的新特性 Env包括所有的新特性 31 | - @babel/plugin-transform-runtime 减少冗余代码 默认的polifill属性已经被废除掉了 32 | - @babel/runtime @babel/plugin-transform-runtime依赖 33 | 34 | ### 解析css的包 35 | 36 | - vue-style-loader 支持服务端渲染 和style-loader功能一样 37 | - css-loader 38 | 39 | ### vue相关 40 | 41 | - vue-loader 处理.vue文件 42 | - vue-template-loader 处理模板编译 43 | 44 | ---------------------------- 45 | npx webpack === node_modules/bin/webpack 打包 46 | 47 | ## webpack5.0 bug记录 48 | 49 | ### 问题一 50 | 51 | webpack5.0与webpack-dev-server不兼容 52 | 53 | npm script 需把 "run":"webpack-dev-server --open"改成 54 | "run":"webpack serve" 55 | 56 | ### 问题2 57 | 58 | vue-style-loader与css-loader 在服务端打包时style样式不生效问题解决方案 59 | 60 | { 61 | test: /\.css$/, 62 | use: [ 63 | "vue-style-loader", 64 | { 65 | loader: "css-loader", 66 | options: { 67 | esModule: false //默认为true 需要设置为false 68 | } 69 | } 70 | ] 71 | } 72 | 73 | ### 问题三 74 | 75 | build目录中 webpack.server.js 76 | const ServerRenderPlugin = require("vue-server-renderer/server-plugin") 报错 77 | 78 | 解决方案 修改vue-server-renderer包中的代码 79 | 80 | 81 | 82 | ### 问题四 83 | 84 | 使用 const ClientRenderPlugin = require("vue-server-renderer/client-plugin"); 85 | const ServerRenderPlugin = require("vue-server-renderer/server-plugin"); 86 | 自动引入js文件时服务端会报错 展示没有解决办法 需要手动引入js文件 87 | 88 | npm run client:build -- --watch 文件变动执行打包编译 89 | 90 | 为什么服务端vue vuex vueRouter 都需要调用一个函数,从函数中获取实例? 91 | 92 | 因为Node.js 服务器是一个长期运行的进程 当代码进入进程时,它将进行一次取值并留存在内存中。也就是会把vue实例保存到内存中 93 | 假如说不用函数返回新的实例,那么每个人访问同一个页面时都会共用同一个实例,那么就会造成数据的污染。 94 | 95 | 96 | 97 | ## 路由集成 98 | 99 | 首屏只渲染一个路由,但是其他路由的逻辑混淆再js文件中。如果需要分开 可以使用路由懒加载。 100 | 每个路由需要返回一个函数 每个服务器都要返回一个路由实例 101 | 102 | 此时的问题 103 | 此时在服务器中执行构建, 104 | 访问localhose:3000/ 应该渲染出对应的组件Foo 但是没有渲染出来 105 | 并且控制台会报错 Failed to execute 'appendChild' on 'Node': This node type does not support this method.at Object.appendChild 106 | 107 | 解造成此问题的原因: 108 | 服务器访问根目录时 router.get("/") 渲染出来的时字符串 它并不知道哪个页面对应哪个路由 所以只会渲染app.vue 109 | 110 | 解决方案: 111 | 112 | server.js中 113 | `render.renderToString({url:'/' })` 114 | 115 | server.enter.js中 116 | 117 | ```js 118 | export default context => { 119 | // 服务端需要调用当前这个文件 去产生一个vue实例 120 | const { app, router } = createApp(); 121 | // context.url 服务端要把对应的路由和此url相匹配 122 | router.push(context.url); // 渲染当前页面对应的路由 123 | return app; //拿这个实例去服务端查找渲染结果 124 | }; 125 | ``` 126 | 127 | 切换到其他路由localhose:3000/bar然后刷新浏览器会报404错误 Not Fount 128 | 129 | **重点**:如果此时是点击切换 那就只是客户端切换 并不是服务端切换。并不会造成服务端重新渲染。 130 | 也可以理解为服务端不认识router-link,解析不出对应的组件, localhose:3000/bar 只有刷新页面时才会走服务端渲染。 131 | 但是此时会报404 因为器服务器根本没有此路径。 132 | 解决方法: 133 | 所以在服务器中还得再配其他路径,使用中间件,使得每个路径渲染对应的页面 134 | 135 | **中间件** 136 | 当找不到路由时会走此逻辑 137 | 如果匹配不到路由就会走此逻辑(当路由不是跟路径时,要跳转到对应的路径,渲染对应的页面) 138 | 如果服务器没有此路径,会渲染当前的app.vue(首页)文件,在渲染时又会重新指向/bar路径对应的页面 139 | 然后 server.entry.js 中router.push(context.url)找对应的组件 140 | 141 | ```js 142 | app.use(async ctx => { 143 | ctx.body = await new Promise((resolve, reject) => { 144 | // 必须写成回调函数的形式否则css样式不生效 145 | render.renderToString( 146 | { 147 | title: "服务", 148 | url: ctx.url //比如当前请求的/bar 那就把/bar传到server.entry.js中的content 149 | }, 150 | (err, data) => { 151 | if (err) reject(err); 152 | resolve(data); 153 | } 154 | ); 155 | }); 156 | }); 157 | ``` 158 | 159 | 也就是先渲染app.vue---->找其他路由对应的组件 160 | 161 | 这也是history模式需要后端支持的原理 162 | 163 | ## Vuex集成 164 | 165 | 为什么vuex需要此判断? 166 | 167 | ```js 168 | if (typeof window !== "undefined" && window.__INITIAL_STATE__) { 169 | store.replaceState(window.__INITIAL_STATE__); 170 | } 171 | ``` 172 | 173 | 因为客户端和服务端各自生成一个vuex实例 而他们两个需要共用一个状态,因此需要服务端状态改变之后传给客户端 174 | 175 | 服务端与客户端各自的用处? 176 | 177 | 服务端用于渲染html 有利于seo 178 | 客户端用于处理js逻辑比如 点击事件 client.bundle.js 179 | 180 | 服务端调用在组件中调用asyncDate() vuex必须返回promise才能生效,并且只有等resolve()执行完成之后才会返回结果 181 | 182 | 如果是服务端调用必须返回 promise 否则不生效 因为在service.entry.js的逻辑是Promise.all() 183 | 自己有里面的所有数据都获取完之后才会渲染app.vue 所以会等待三秒才渲染数据 184 | 只写setTimeout 不生效 因为setTimeout是异步的,在vuex实例渲染完成后才被调用,此时页面已经被当成字符串渲染到浏览器上了。 185 | 186 | 哪些请求放在ajax哪些放在服务端请求? 187 | 188 | 被爬虫爬取,比如新闻列表的数据 由服务端返回 189 | 190 | ## 流程大致总结 191 | 192 | 主入口文件 193 | 194 | - 服务端入口文件 195 | - 客户端入口文件 196 | 197 | webpack 198 | 199 | - base.js 200 | - 服务端配置 201 | - 客户端配置 202 | - merge-webpack 203 | 204 | vue-server-renderer 205 | 206 | - createRender() createBundleRender() 207 | 208 | - renderTostring() renderToStream() 209 | 210 | ### 主流程 211 | 212 | - webpack.server.js -> 入口文件 server.entry.js(函数生成每个实例)-> npm run server:build->服务端文件打包到dist目录 213 | 214 | - webpack.client.js->入口文件 server.entry.js ->npm run client:build->客户端打包到dist目录 215 | 216 | - Koa-> vue-server-renderer->render.createBundleRender()引入打包好的服务端文件和模板->render.renderToStream()配置模板属性+生成html字符串->koa中间件监听dist目录->在模板中手动引入客户端打包好的bundle.js文件->挂载#app激活事件->返回给客户端。 217 | 218 | css->vue-style-loader 219 | 220 | -配置meta标签 221 | 222 | - 在option中设置title 223 | - 客户端:document.title=this.$options.title 224 | - 服务端:this.$ssrContext=title 225 | 226 | ### 配置路由 227 | 228 | 引入路由->每个路由都已函数的形式返回->koa中间件捕获到history路径->把url传给render.renderToString->server.entry.js接受到路径 229 | router.push(context.url)渲染当前页面对应的路由 230 | 231 | router.onReady() router.getMatchedComponents() 232 | 233 | ### 配置vuex 234 | 235 | 引入vuex->每个路由都已函数的形式返回->在匹配到的每个组件中调用asyncData方法动态传入store-> 236 | 改变store的状态->更新(此时会等待promise执行完成再渲染页面)-> 237 | 再拿到状态->context.state = store.state->把vuex的状态挂载到上下文中,会将状态挂载到window上-> 238 | 当客户端执行vuex时把状态替换掉store.replaceState(window.__INITIAL_STATE__); 239 | -------------------------------------------------------------------------------- /SSR-3/笔记: -------------------------------------------------------------------------------- 1 | # webpack5.0+Vue+SSR+vue-router+vuex 2 | ![](https://p6-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0eb6c4b857fe413bb2038e6601722155~tplv-k3u1fbpfcp-watermark.image) 3 | ## 一些包 4 | ### webpack相关 5 | - webpack 6 | - webpack-cli 命令行解析工具 4.0之前是一起的 4.0之后拆开了 需要安装 7 | - webpack-dev-server 8 | - html-webpack-plugin 9 | - webpack-merge 10 | 11 | ### es6转es5 12 | - babel-loader es6=>es5 webpack中接入babel 13 | - @babel/core babel-loader依赖 14 | - @babel/preset-env 加入新的语法特性 比如2015年加入的新特性 Env包括所有的新特性 15 | - @babel/plugin-transform-runtime 减少冗余代码 默认的polifill属性已经被废除掉了 16 | - @babel/runtime @babel/plugin-transform-runtime依赖 17 | 18 | ### 解析css的包 19 | - vue-style-loader 支持服务端渲染 和style-loader功能一样 20 | - css-loader 21 | 22 | ### vue相关 23 | - vue-loader 处理.vue文件 24 | - vue-template-loader 处理模板编译 25 | 26 | 27 | 28 | ---------------------------- 29 | npx webpack === node_modules/bin/webpack 打包 30 | 31 | 32 | 33 | ## webpack5.0 bug记录 34 | 35 | ### 问题一 36 | webpack5.0与webpack-dev-server不兼容 37 | 38 | npm script 需把 "run":"webpack-dev-server --open"改成 39 | "run":"webpack serve" 40 | 41 | 42 | ### 问题2 43 | vue-style-loader与css-loader 在服务端打包时style样式不生效问题解决方案 44 | 45 | ```js 46 | { 47 | test: /\.css$/, 48 | use: [ 49 | "vue-style-loader", 50 | { 51 | loader: "css-loader", 52 | options: { 53 | esModule: false //默认为true 需要设置为false 54 | } 55 | } 56 | ] 57 | } 58 | ``` 59 | 60 | 61 | ### 问题三 62 | build目录中 webpack.server.js 63 | const ServerRenderPlugin = require("vue-server-renderer/server-plugin") 报错 64 | 65 | 解决方案 修改vue-server-renderer包中的代码 66 | 67 | https://github.com/vuejs/vue/issues/11718#issuecomment-717786088 68 | 69 | 70 | ### 问题四 71 | 使用 72 | ```js 73 | const ClientRenderPlugin = require("vue-server-renderer/client-plugin"); 74 | const ServerRenderPlugin = require("vue-server-renderer/server-plugin"); 75 | ``` 76 | 自动引入js文件时服务端会报错 暂时没有解决办法 需要手动引入js文件 77 | 78 | 79 | 80 | 81 | npm run client:build -- --watch 文件变动执行打包编译 82 | 83 | 为什么服务端vue vuex vueRouter 都需要调用一个函数,从函数中获取实例? 84 | 85 | 因为Node.js 服务器是一个长期运行的进程 当代码进入进程时,它将进行一次取值并留存在内存中。也就是会把vue实例保存到内存中 86 | 假如说不用函数返回新的实例,那么每个人访问同一个页面时都会共用同一个实例,那么就会造成数据的污染。 87 | 88 | https://ssr.vuejs.org/zh/guide/structure.html 89 | 90 | 91 | ## 路由集成 92 | 首屏只渲染一个路由,但是其他路由的逻辑混淆再js文件中。如果需要分开 可以使用路由懒加载。 93 | 每个路由需要返回一个函数 每个服务器都要返回一个路由实例 94 | 95 | 96 | 此时的问题 97 | 98 | 此时在服务器中执行构建, 99 | 访问localhose:3000/ 应该渲染出对应的组件Foo 但是没有渲染出来 100 | 并且控制台会报错 Failed to execute 'appendChild' on 'Node': This node type does not support this method.at Object.appendChild 101 | 102 | 解造成此问题的原因: 103 | 服务器访问根目录时 router.get("/") 渲染出来的时字符串 它并不知道哪个页面对应哪个路由 所以只会渲染app.vue 104 | 105 | 解决方案: 106 | 107 | server.js中 108 | `render.renderToString({url:'/' })` 109 | 110 | server.enter.js中 111 | 112 | ```js 113 | export default context => { 114 | // 服务端需要调用当前这个文件 去产生一个vue实例 115 | const { app, router } = createApp(); 116 | // context.url 服务端要把对应的路由和此url相匹配 117 | router.push(context.url); // 渲染当前页面对应的路由 118 | return app; //拿这个实例去服务端查找渲染结果 119 | }; 120 | ``` 121 | 122 | 切换到其他路由localhose:3000/bar然后刷新浏览器会报404错误 Not Fount 123 | 124 | **重点**:如果此时是点击切换 那就只是客户端切换 并不是服务端切换。并不会造成服务端重新渲染。 125 | 也可以理解为服务端不认识router-link,解析不出对应的组件, localhose:3000/bar 只有刷新页面时才会走服务端渲染。 126 | 但是此时会报404 因为器服务器根本没有此路径。 127 | 解决方法: 128 | 所以在服务器中还得再配其他路径,使用中间件,使得每个路径渲染对应的页面 129 | 130 | **中间件** 131 | 当找不到路由时会走此逻辑 132 | 如果匹配不到路由就会走此逻辑(当路由不是根路径时,要跳转到对应的路径,渲染对应的页面) 133 | 如果服务器没有此路径,会渲染当前的app.vue(首页)文件,在渲染时又会重新指向/bar路径对应的页面 134 | 然后 server.entry.js 中router.push(context.url)找对应的组件 135 | 136 | app.use(async ctx => { 137 | ctx.body = await new Promise((resolve, reject) => { 138 | // 必须写成回调函数的形式否则css样式不生效 139 | render.renderToString( 140 | { 141 | title: "服务", 142 | url: ctx.url //比如当前请求的/bar 那就把/bar传到server.entry.js中的content 143 | }, 144 | (err, data) => { 145 | if (err) reject(err); 146 | resolve(data); 147 | } 148 | ); 149 | }); 150 | }); 151 | 152 | 也就是先渲染app.vue---->找其他路由对应的组件 153 | 如果是单页面 koa中间件会去监听生成的bundle.js文件(中间件回去监听dist目录下的所有文件) 154 | 这也是history模式需要后端支持的原理 155 | 156 | ## Vuex集成 157 | 158 | Vuex中为什么需要此判断? 159 | 160 | if (typeof window !== "undefined" && window.__INITIAL_STATE__) { 161 | store.replaceState(window.__INITIAL_STATE__); 162 | } 163 | 164 | 165 | 因为客户端和服务端各自生成一个vuex实例 而他们两个需要共用一个状态,因此需要服务端状态改变之后传给客户端 166 | 167 | 168 | 服务端与客户端各自的用处? 169 | 170 | 服务端用于渲染html 有利于seo 171 | 客户端用于处理js逻辑比如 点击事件 client.bundle.js 172 | 173 | 服务端调用在组件中调用asyncDate() vuex必须返回promise才能生效,并且只有等resolve()执行完成之后才会返回结果 174 | 175 | 如果是服务端调用必须返回 promise 否则不生效 因为在service.entry.js的逻辑是Promise.all() 176 | 自己有里面的所有数据都获取完之后才会渲染app.vue 所以会等待三秒才渲染数据 177 | 只写setTimeout 不生效 因为setTimeout是异步的,在vuex实例渲染完成后才被调用,此时页面已经被当成字符串渲染到浏览器上了。 178 | 179 | 哪些请求放在ajax哪些放在服务端请求? 180 | 181 | 被爬虫爬取,比如新闻列表的数据 由服务端返回 182 | 183 | 184 | ## 使用 185 | - 在SSR-3目录中 npm install 安装依赖 186 | - 打包服务端 npm run server:build 187 | - 打包客户端 npm run client:build 188 | 189 | - 在dist目录index.ssr.html中引入客户端代码`` 190 | 191 | - 执行服务端脚本 `node server.js` 192 | 193 | ## 项目地址 194 | 195 | https://github.com/wensiyuanseven/Vue-SSR 196 | 197 | 198 | 199 | 流程大致总结 200 | 201 | 主入口文件 - 服务端入口文件 202 | - 客户端入口文件 203 | webpack - base.js 204 | - 服务端配置 205 | - 客户端配置 206 | - merge-webpack 207 | vue-server-renderer 两个方法 createRender() createBundleRender() 208 | renderTostring() renderToStream() 209 | 210 | 流程 211 | webpack.server.js -> 入口文件 server.entry.js(函数生成每个实例)-> npm run server:build->服务端文件打包到dist目录 212 | 213 | webpack.client.js->入口文件 server.entry.js ->npm run client:build->客户端打包到dist目录 214 | 215 | Koa-> vue-server-renderer->render.createBundleRender()引入打包好的服务端文件和模板->render.renderToStream()配置模板属性+生成html字符串 216 | ->koa中间件监听dist目录->在模板中手动引入客户端打包好的bundle.js文件->挂载#app激活事件->返回给客户端。 217 | 218 | css->vue-style-loader 219 | 220 | 配置meta标签->在option中设置title 221 | 客户端:document.title=this.$options.title 222 | 服务端:this.$ssrContext=title 223 | 224 | 配置路由 225 | 226 | 引入路由->每个路由都已函数的形式返回->koa中间件捕获到history路径->把url传给render.renderToString->server.entry.js接受到路径 227 | router.push(context.url)渲染当前页面对应的路由 228 | 229 | router.onReady() router.getMatchedComponents() 230 | 231 | 232 | 配置vuex 233 | 234 | 引入vuex->每个路由都已函数的形式返回->在匹配到的每个组件中调用asyncData方法动态传入store-> 235 | 改变store的状态->更新(此时会等待promise执行完成再渲染页面)-> 236 | 再拿到状态->context.state = store.state->把vuex的状态挂载到上下文中,会将状态挂载到window上-> 237 | 当客户端执行vuex时把状态替换掉 store.replaceState(window.__INITIAL_STATE__); 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | -------------------------------------------------------------------------------- /基本的服务端渲染/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "base-ssr", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "accepts": { 8 | "version": "1.3.7", 9 | "resolved": "https://registry.npm.taobao.org/accepts/download/accepts-1.3.7.tgz", 10 | "integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=", 11 | "requires": { 12 | "mime-types": "~2.1.24", 13 | "negotiator": "0.6.2" 14 | } 15 | }, 16 | "ansi-regex": { 17 | "version": "2.1.1", 18 | "resolved": "https://registry.npm.taobao.org/ansi-regex/download/ansi-regex-2.1.1.tgz", 19 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" 20 | }, 21 | "ansi-styles": { 22 | "version": "2.2.1", 23 | "resolved": "https://registry.npm.taobao.org/ansi-styles/download/ansi-styles-2.2.1.tgz", 24 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" 25 | }, 26 | "any-promise": { 27 | "version": "1.3.0", 28 | "resolved": "https://registry.npm.taobao.org/any-promise/download/any-promise-1.3.0.tgz", 29 | "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" 30 | }, 31 | "cache-content-type": { 32 | "version": "1.0.1", 33 | "resolved": "https://registry.npm.taobao.org/cache-content-type/download/cache-content-type-1.0.1.tgz", 34 | "integrity": "sha1-A1zeKwjuISn0qDFeqPAKANuhRTw=", 35 | "requires": { 36 | "mime-types": "^2.1.18", 37 | "ylru": "^1.2.0" 38 | } 39 | }, 40 | "chalk": { 41 | "version": "1.1.3", 42 | "resolved": "https://registry.npm.taobao.org/chalk/download/chalk-1.1.3.tgz", 43 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 44 | "requires": { 45 | "ansi-styles": "^2.2.1", 46 | "escape-string-regexp": "^1.0.2", 47 | "has-ansi": "^2.0.0", 48 | "strip-ansi": "^3.0.0", 49 | "supports-color": "^2.0.0" 50 | } 51 | }, 52 | "co": { 53 | "version": "4.6.0", 54 | "resolved": "https://registry.npm.taobao.org/co/download/co-4.6.0.tgz", 55 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" 56 | }, 57 | "content-disposition": { 58 | "version": "0.5.3", 59 | "resolved": "https://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.3.tgz", 60 | "integrity": "sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70=", 61 | "requires": { 62 | "safe-buffer": "5.1.2" 63 | } 64 | }, 65 | "content-type": { 66 | "version": "1.0.4", 67 | "resolved": "https://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz", 68 | "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=" 69 | }, 70 | "cookies": { 71 | "version": "0.8.0", 72 | "resolved": "https://registry.npm.taobao.org/cookies/download/cookies-0.8.0.tgz?cache=0&sync_timestamp=1570851324736&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcookies%2Fdownload%2Fcookies-0.8.0.tgz", 73 | "integrity": "sha1-EpPOSzkXQKhAbjyYcOgoxLVPP5A=", 74 | "requires": { 75 | "depd": "~2.0.0", 76 | "keygrip": "~1.1.0" 77 | }, 78 | "dependencies": { 79 | "depd": { 80 | "version": "2.0.0", 81 | "resolved": "https://registry.npm.taobao.org/depd/download/depd-2.0.0.tgz", 82 | "integrity": "sha1-tpYWPMdXVg0JzyLMj60Vcbeedt8=" 83 | } 84 | } 85 | }, 86 | "debug": { 87 | "version": "3.1.0", 88 | "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz?cache=0&sync_timestamp=1600502873540&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-3.1.0.tgz", 89 | "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", 90 | "requires": { 91 | "ms": "2.0.0" 92 | } 93 | }, 94 | "deep-equal": { 95 | "version": "1.0.1", 96 | "resolved": "https://registry.npm.taobao.org/deep-equal/download/deep-equal-1.0.1.tgz", 97 | "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" 98 | }, 99 | "delegates": { 100 | "version": "1.0.0", 101 | "resolved": "https://registry.npm.taobao.org/delegates/download/delegates-1.0.0.tgz", 102 | "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" 103 | }, 104 | "depd": { 105 | "version": "1.1.2", 106 | "resolved": "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz", 107 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 108 | }, 109 | "destroy": { 110 | "version": "1.0.4", 111 | "resolved": "https://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz", 112 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 113 | }, 114 | "ee-first": { 115 | "version": "1.1.1", 116 | "resolved": "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz", 117 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 118 | }, 119 | "encodeurl": { 120 | "version": "1.0.2", 121 | "resolved": "https://registry.npm.taobao.org/encodeurl/download/encodeurl-1.0.2.tgz", 122 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 123 | }, 124 | "escape-html": { 125 | "version": "1.0.3", 126 | "resolved": "https://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz", 127 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 128 | }, 129 | "escape-string-regexp": { 130 | "version": "1.0.5", 131 | "resolved": "https://registry.npm.taobao.org/escape-string-regexp/download/escape-string-regexp-1.0.5.tgz", 132 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" 133 | }, 134 | "fresh": { 135 | "version": "0.5.2", 136 | "resolved": "https://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz", 137 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 138 | }, 139 | "function-bind": { 140 | "version": "1.1.1", 141 | "resolved": "https://registry.npm.taobao.org/function-bind/download/function-bind-1.1.1.tgz", 142 | "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=" 143 | }, 144 | "has": { 145 | "version": "1.0.3", 146 | "resolved": "https://registry.npm.taobao.org/has/download/has-1.0.3.tgz", 147 | "integrity": "sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y=", 148 | "requires": { 149 | "function-bind": "^1.1.1" 150 | } 151 | }, 152 | "has-ansi": { 153 | "version": "2.0.0", 154 | "resolved": "https://registry.npm.taobao.org/has-ansi/download/has-ansi-2.0.0.tgz", 155 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 156 | "requires": { 157 | "ansi-regex": "^2.0.0" 158 | } 159 | }, 160 | "hash-sum": { 161 | "version": "1.0.2", 162 | "resolved": "https://registry.npm.taobao.org/hash-sum/download/hash-sum-1.0.2.tgz", 163 | "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=" 164 | }, 165 | "he": { 166 | "version": "1.2.0", 167 | "resolved": "https://registry.npm.taobao.org/he/download/he-1.2.0.tgz", 168 | "integrity": "sha1-hK5l+n6vsWX922FWauFLrwVmTw8=" 169 | }, 170 | "http-assert": { 171 | "version": "1.4.1", 172 | "resolved": "https://registry.npm.taobao.org/http-assert/download/http-assert-1.4.1.tgz", 173 | "integrity": "sha1-xfcl1neqfoc+9zYZm4lobM6zeHg=", 174 | "requires": { 175 | "deep-equal": "~1.0.1", 176 | "http-errors": "~1.7.2" 177 | }, 178 | "dependencies": { 179 | "http-errors": { 180 | "version": "1.7.3", 181 | "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.3.tgz?cache=0&sync_timestamp=1593407611415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.7.3.tgz", 182 | "integrity": "sha1-bGGeT5xgMIw4UZSYwU+7EKrOuwY=", 183 | "requires": { 184 | "depd": "~1.1.2", 185 | "inherits": "2.0.4", 186 | "setprototypeof": "1.1.1", 187 | "statuses": ">= 1.5.0 < 2", 188 | "toidentifier": "1.0.0" 189 | } 190 | } 191 | } 192 | }, 193 | "http-errors": { 194 | "version": "1.8.0", 195 | "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.8.0.tgz?cache=0&sync_timestamp=1593407611415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.8.0.tgz", 196 | "integrity": "sha1-ddG75JfhBE9R5O6ecEpi8o0zZQc=", 197 | "requires": { 198 | "depd": "~1.1.2", 199 | "inherits": "2.0.4", 200 | "setprototypeof": "1.2.0", 201 | "statuses": ">= 1.5.0 < 2", 202 | "toidentifier": "1.0.0" 203 | }, 204 | "dependencies": { 205 | "setprototypeof": { 206 | "version": "1.2.0", 207 | "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.2.0.tgz", 208 | "integrity": "sha1-ZsmiSnP5/CjL5msJ/tPTPcrxtCQ=" 209 | } 210 | } 211 | }, 212 | "inherits": { 213 | "version": "2.0.4", 214 | "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz", 215 | "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=" 216 | }, 217 | "is-core-module": { 218 | "version": "2.0.0", 219 | "resolved": "https://registry.npm.taobao.org/is-core-module/download/is-core-module-2.0.0.tgz", 220 | "integrity": "sha1-WFMbcK7R23wOjU6xoKLR3dZL0S0=", 221 | "requires": { 222 | "has": "^1.0.3" 223 | } 224 | }, 225 | "is-generator-function": { 226 | "version": "1.0.7", 227 | "resolved": "https://registry.npm.taobao.org/is-generator-function/download/is-generator-function-1.0.7.tgz", 228 | "integrity": "sha1-0hMuUpuwAAp/gHlNS99c1eWBNSI=" 229 | }, 230 | "keygrip": { 231 | "version": "1.1.0", 232 | "resolved": "https://registry.npm.taobao.org/keygrip/download/keygrip-1.1.0.tgz", 233 | "integrity": "sha1-hxsWgdXhWcYqRFsMdLYV4JF+ciY=", 234 | "requires": { 235 | "tsscmp": "1.0.6" 236 | } 237 | }, 238 | "koa": { 239 | "version": "2.13.0", 240 | "resolved": "https://registry.npm.taobao.org/koa/download/koa-2.13.0.tgz?cache=0&sync_timestamp=1592754966586&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkoa%2Fdownload%2Fkoa-2.13.0.tgz", 241 | "integrity": "sha1-JSF+Be/TNYp+Xd7ADwo4DJtxtQE=", 242 | "requires": { 243 | "accepts": "^1.3.5", 244 | "cache-content-type": "^1.0.0", 245 | "content-disposition": "~0.5.2", 246 | "content-type": "^1.0.4", 247 | "cookies": "~0.8.0", 248 | "debug": "~3.1.0", 249 | "delegates": "^1.0.0", 250 | "depd": "^1.1.2", 251 | "destroy": "^1.0.4", 252 | "encodeurl": "^1.0.2", 253 | "escape-html": "^1.0.3", 254 | "fresh": "~0.5.2", 255 | "http-assert": "^1.3.0", 256 | "http-errors": "^1.6.3", 257 | "is-generator-function": "^1.0.7", 258 | "koa-compose": "^4.1.0", 259 | "koa-convert": "^1.2.0", 260 | "on-finished": "^2.3.0", 261 | "only": "~0.0.2", 262 | "parseurl": "^1.3.2", 263 | "statuses": "^1.5.0", 264 | "type-is": "^1.6.16", 265 | "vary": "^1.1.2" 266 | } 267 | }, 268 | "koa-compose": { 269 | "version": "4.1.0", 270 | "resolved": "https://registry.npm.taobao.org/koa-compose/download/koa-compose-4.1.0.tgz", 271 | "integrity": "sha1-UHMGuTcZAdtBEhyBLpI9DWfT6Hc=" 272 | }, 273 | "koa-convert": { 274 | "version": "1.2.0", 275 | "resolved": "https://registry.npm.taobao.org/koa-convert/download/koa-convert-1.2.0.tgz", 276 | "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=", 277 | "requires": { 278 | "co": "^4.6.0", 279 | "koa-compose": "^3.0.0" 280 | }, 281 | "dependencies": { 282 | "koa-compose": { 283 | "version": "3.2.1", 284 | "resolved": "https://registry.npm.taobao.org/koa-compose/download/koa-compose-3.2.1.tgz", 285 | "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=", 286 | "requires": { 287 | "any-promise": "^1.1.0" 288 | } 289 | } 290 | } 291 | }, 292 | "koa-router": { 293 | "version": "9.4.0", 294 | "resolved": "https://registry.npm.taobao.org/koa-router/download/koa-router-9.4.0.tgz?cache=0&sync_timestamp=1597368200163&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkoa-router%2Fdownload%2Fkoa-router-9.4.0.tgz", 295 | "integrity": "sha1-e9PNT2JHJW5LVvuyIDveOFGswVo=", 296 | "requires": { 297 | "debug": "^4.1.1", 298 | "http-errors": "^1.7.3", 299 | "koa-compose": "^4.1.0", 300 | "methods": "^1.1.2", 301 | "path-to-regexp": "^6.1.0" 302 | }, 303 | "dependencies": { 304 | "debug": { 305 | "version": "4.2.0", 306 | "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.2.0.tgz?cache=0&sync_timestamp=1600502873540&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.2.0.tgz", 307 | "integrity": "sha1-fxUPk5IOlMWPVXTC/QGjEQ7/5/E=", 308 | "requires": { 309 | "ms": "2.1.2" 310 | } 311 | }, 312 | "ms": { 313 | "version": "2.1.2", 314 | "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz", 315 | "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=" 316 | } 317 | } 318 | }, 319 | "koa-send": { 320 | "version": "5.0.1", 321 | "resolved": "https://registry.npm.taobao.org/koa-send/download/koa-send-5.0.1.tgz", 322 | "integrity": "sha1-Odzuv6+zldDWC+r/ujpwtPVD/nk=", 323 | "requires": { 324 | "debug": "^4.1.1", 325 | "http-errors": "^1.7.3", 326 | "resolve-path": "^1.4.0" 327 | }, 328 | "dependencies": { 329 | "debug": { 330 | "version": "4.2.0", 331 | "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.2.0.tgz?cache=0&sync_timestamp=1600502873540&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.2.0.tgz", 332 | "integrity": "sha1-fxUPk5IOlMWPVXTC/QGjEQ7/5/E=", 333 | "requires": { 334 | "ms": "2.1.2" 335 | } 336 | }, 337 | "ms": { 338 | "version": "2.1.2", 339 | "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz", 340 | "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=" 341 | } 342 | } 343 | }, 344 | "koa-static": { 345 | "version": "5.0.0", 346 | "resolved": "https://registry.npm.taobao.org/koa-static/download/koa-static-5.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkoa-static%2Fdownload%2Fkoa-static-5.0.0.tgz", 347 | "integrity": "sha1-XpL8lrU3rVIZ9CUxnJW2R3J3aUM=", 348 | "requires": { 349 | "debug": "^3.1.0", 350 | "koa-send": "^5.0.0" 351 | } 352 | }, 353 | "lodash._reinterpolate": { 354 | "version": "3.0.0", 355 | "resolved": "https://registry.npm.taobao.org/lodash._reinterpolate/download/lodash._reinterpolate-3.0.0.tgz", 356 | "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=" 357 | }, 358 | "lodash.template": { 359 | "version": "4.5.0", 360 | "resolved": "https://registry.npm.taobao.org/lodash.template/download/lodash.template-4.5.0.tgz", 361 | "integrity": "sha1-+XYZXPPzR9DV9SSDVp/oAxzM6Ks=", 362 | "requires": { 363 | "lodash._reinterpolate": "^3.0.0", 364 | "lodash.templatesettings": "^4.0.0" 365 | } 366 | }, 367 | "lodash.templatesettings": { 368 | "version": "4.2.0", 369 | "resolved": "https://registry.npm.taobao.org/lodash.templatesettings/download/lodash.templatesettings-4.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash.templatesettings%2Fdownload%2Flodash.templatesettings-4.2.0.tgz", 370 | "integrity": "sha1-5IExDwSdPPbUfpEq0JMTsVTw+zM=", 371 | "requires": { 372 | "lodash._reinterpolate": "^3.0.0" 373 | } 374 | }, 375 | "lodash.uniq": { 376 | "version": "4.5.0", 377 | "resolved": "https://registry.npm.taobao.org/lodash.uniq/download/lodash.uniq-4.5.0.tgz", 378 | "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" 379 | }, 380 | "media-typer": { 381 | "version": "0.3.0", 382 | "resolved": "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz", 383 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 384 | }, 385 | "methods": { 386 | "version": "1.1.2", 387 | "resolved": "https://registry.npm.taobao.org/methods/download/methods-1.1.2.tgz", 388 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 389 | }, 390 | "mime-db": { 391 | "version": "1.44.0", 392 | "resolved": "https://registry.npm.taobao.org/mime-db/download/mime-db-1.44.0.tgz?cache=0&sync_timestamp=1600831212519&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-db%2Fdownload%2Fmime-db-1.44.0.tgz", 393 | "integrity": "sha1-+hHF6wrKEzS0Izy01S8QxaYnL5I=" 394 | }, 395 | "mime-types": { 396 | "version": "2.1.27", 397 | "resolved": "https://registry.npm.taobao.org/mime-types/download/mime-types-2.1.27.tgz", 398 | "integrity": "sha1-R5SfmOJ56lMRn1ci4PNOUpvsAJ8=", 399 | "requires": { 400 | "mime-db": "1.44.0" 401 | } 402 | }, 403 | "ms": { 404 | "version": "2.0.0", 405 | "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", 406 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 407 | }, 408 | "negotiator": { 409 | "version": "0.6.2", 410 | "resolved": "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz", 411 | "integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs=" 412 | }, 413 | "on-finished": { 414 | "version": "2.3.0", 415 | "resolved": "https://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz", 416 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 417 | "requires": { 418 | "ee-first": "1.1.1" 419 | } 420 | }, 421 | "only": { 422 | "version": "0.0.2", 423 | "resolved": "https://registry.npm.taobao.org/only/download/only-0.0.2.tgz", 424 | "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q=" 425 | }, 426 | "parseurl": { 427 | "version": "1.3.3", 428 | "resolved": "https://registry.npm.taobao.org/parseurl/download/parseurl-1.3.3.tgz", 429 | "integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ=" 430 | }, 431 | "path-is-absolute": { 432 | "version": "1.0.1", 433 | "resolved": "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz", 434 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 435 | }, 436 | "path-parse": { 437 | "version": "1.0.6", 438 | "resolved": "https://registry.npm.taobao.org/path-parse/download/path-parse-1.0.6.tgz", 439 | "integrity": "sha1-1i27VnlAXXLEc37FhgDp3c8G0kw=" 440 | }, 441 | "path-to-regexp": { 442 | "version": "6.2.0", 443 | "resolved": "https://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-6.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-to-regexp%2Fdownload%2Fpath-to-regexp-6.2.0.tgz", 444 | "integrity": "sha1-97OAMzYQTDRoia3s5hRmkjBkXzg=" 445 | }, 446 | "randombytes": { 447 | "version": "2.1.0", 448 | "resolved": "https://registry.npm.taobao.org/randombytes/download/randombytes-2.1.0.tgz", 449 | "integrity": "sha1-32+ENy8CcNxlzfYpE0mrekc9Tyo=", 450 | "requires": { 451 | "safe-buffer": "^5.1.0" 452 | } 453 | }, 454 | "resolve": { 455 | "version": "1.18.1", 456 | "resolved": "https://registry.npm.taobao.org/resolve/download/resolve-1.18.1.tgz?cache=0&sync_timestamp=1603313534612&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fresolve%2Fdownload%2Fresolve-1.18.1.tgz", 457 | "integrity": "sha1-AY/LLFsgfSpkJK7jYcWiZtqPQTA=", 458 | "requires": { 459 | "is-core-module": "^2.0.0", 460 | "path-parse": "^1.0.6" 461 | } 462 | }, 463 | "resolve-path": { 464 | "version": "1.4.0", 465 | "resolved": "https://registry.npm.taobao.org/resolve-path/download/resolve-path-1.4.0.tgz", 466 | "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=", 467 | "requires": { 468 | "http-errors": "~1.6.2", 469 | "path-is-absolute": "1.0.1" 470 | }, 471 | "dependencies": { 472 | "http-errors": { 473 | "version": "1.6.3", 474 | "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.6.3.tgz?cache=0&sync_timestamp=1593407611415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.6.3.tgz", 475 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", 476 | "requires": { 477 | "depd": "~1.1.2", 478 | "inherits": "2.0.3", 479 | "setprototypeof": "1.1.0", 480 | "statuses": ">= 1.4.0 < 2" 481 | } 482 | }, 483 | "inherits": { 484 | "version": "2.0.3", 485 | "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz", 486 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 487 | }, 488 | "setprototypeof": { 489 | "version": "1.1.0", 490 | "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.0.tgz", 491 | "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY=" 492 | } 493 | } 494 | }, 495 | "safe-buffer": { 496 | "version": "5.1.2", 497 | "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz", 498 | "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0=" 499 | }, 500 | "serialize-javascript": { 501 | "version": "3.1.0", 502 | "resolved": "https://registry.npm.taobao.org/serialize-javascript/download/serialize-javascript-3.1.0.tgz?cache=0&sync_timestamp=1599740666792&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fserialize-javascript%2Fdownload%2Fserialize-javascript-3.1.0.tgz", 503 | "integrity": "sha1-i/OpFwcSZk7yVhtEtpHq/jmSFOo=", 504 | "requires": { 505 | "randombytes": "^2.1.0" 506 | } 507 | }, 508 | "setprototypeof": { 509 | "version": "1.1.1", 510 | "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz", 511 | "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM=" 512 | }, 513 | "source-map": { 514 | "version": "0.5.6", 515 | "resolved": "https://registry.npm.taobao.org/source-map/download/source-map-0.5.6.tgz", 516 | "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=" 517 | }, 518 | "statuses": { 519 | "version": "1.5.0", 520 | "resolved": "https://registry.npm.taobao.org/statuses/download/statuses-1.5.0.tgz?cache=0&sync_timestamp=1587355518192&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstatuses%2Fdownload%2Fstatuses-1.5.0.tgz", 521 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 522 | }, 523 | "strip-ansi": { 524 | "version": "3.0.1", 525 | "resolved": "https://registry.npm.taobao.org/strip-ansi/download/strip-ansi-3.0.1.tgz", 526 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 527 | "requires": { 528 | "ansi-regex": "^2.0.0" 529 | } 530 | }, 531 | "supports-color": { 532 | "version": "2.0.0", 533 | "resolved": "https://registry.npm.taobao.org/supports-color/download/supports-color-2.0.0.tgz?cache=0&sync_timestamp=1598611719015&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsupports-color%2Fdownload%2Fsupports-color-2.0.0.tgz", 534 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" 535 | }, 536 | "toidentifier": { 537 | "version": "1.0.0", 538 | "resolved": "https://registry.npm.taobao.org/toidentifier/download/toidentifier-1.0.0.tgz", 539 | "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=" 540 | }, 541 | "tsscmp": { 542 | "version": "1.0.6", 543 | "resolved": "https://registry.npm.taobao.org/tsscmp/download/tsscmp-1.0.6.tgz", 544 | "integrity": "sha1-hbmVg6w1iexL/vgltQAKqRHWBes=" 545 | }, 546 | "type-is": { 547 | "version": "1.6.18", 548 | "resolved": "https://registry.npm.taobao.org/type-is/download/type-is-1.6.18.tgz", 549 | "integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=", 550 | "requires": { 551 | "media-typer": "0.3.0", 552 | "mime-types": "~2.1.24" 553 | } 554 | }, 555 | "vary": { 556 | "version": "1.1.2", 557 | "resolved": "https://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz", 558 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 559 | }, 560 | "vue": { 561 | "version": "2.6.12", 562 | "resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz", 563 | "integrity": "sha1-9evU+mvShpQD4pqJau1JBEVskSM=" 564 | }, 565 | "vue-router": { 566 | "version": "3.4.7", 567 | "resolved": "https://registry.npm.taobao.org/vue-router/download/vue-router-3.4.7.tgz?cache=0&sync_timestamp=1603457247867&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue-router%2Fdownload%2Fvue-router-3.4.7.tgz", 568 | "integrity": "sha1-vxibr9FvTk73g8SmJQowkPLB+hs=" 569 | }, 570 | "vue-server-renderer": { 571 | "version": "2.6.12", 572 | "resolved": "https://registry.npm.taobao.org/vue-server-renderer/download/vue-server-renderer-2.6.12.tgz", 573 | "integrity": "sha1-qMucSUOe8gUpPLQcNdDSsFQWU6U=", 574 | "requires": { 575 | "chalk": "^1.1.3", 576 | "hash-sum": "^1.0.2", 577 | "he": "^1.1.0", 578 | "lodash.template": "^4.5.0", 579 | "lodash.uniq": "^4.5.0", 580 | "resolve": "^1.2.0", 581 | "serialize-javascript": "^3.1.0", 582 | "source-map": "0.5.6" 583 | } 584 | }, 585 | "vuex": { 586 | "version": "3.5.1", 587 | "resolved": "https://registry.npm.taobao.org/vuex/download/vuex-3.5.1.tgz", 588 | "integrity": "sha1-8bjc6mSbwlJUz09DWAgdv12hiz0=" 589 | }, 590 | "ylru": { 591 | "version": "1.2.1", 592 | "resolved": "https://registry.npm.taobao.org/ylru/download/ylru-1.2.1.tgz", 593 | "integrity": "sha1-9Xa2M0FUeYnB3nuiiHYJI7J/6E8=" 594 | } 595 | } 596 | } 597 | -------------------------------------------------------------------------------- /单页面配置/dist/bundle.js: -------------------------------------------------------------------------------- 1 | /*! For license information please see bundle.js.LICENSE.txt */ 2 | (()=>{"use strict";var t={};t.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}();var e=Object.freeze({});function n(t){return null==t}function r(t){return null!=t}function o(t){return!0===t}function i(t){return"string"==typeof t||"number"==typeof t||"symbol"==typeof t||"boolean"==typeof t}function a(t){return null!==t&&"object"==typeof t}var s=Object.prototype.toString;function c(t){return"[object Object]"===s.call(t)}function u(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e&&isFinite(t)}function l(t){return r(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function f(t){return null==t?"":Array.isArray(t)||c(t)&&t.toString===s?JSON.stringify(t,null,2):String(t)}function p(t){var e=parseFloat(t);return isNaN(e)?t:e}function d(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o-1)return t.splice(n,1)}}var m=Object.prototype.hasOwnProperty;function y(t,e){return m.call(t,e)}function _(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}var g=/-(\w)/g,b=_((function(t){return t.replace(g,(function(t,e){return e?e.toUpperCase():""}))})),C=_((function(t){return t.charAt(0).toUpperCase()+t.slice(1)})),w=/\B([A-Z])/g,$=_((function(t){return t.replace(w,"-$1").toLowerCase()})),A=Function.prototype.bind?function(t,e){return t.bind(e)}:function(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n};function x(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function O(t,e){for(var n in e)t[n]=e[n];return t}function k(t){for(var e={},n=0;n0,X=W&&W.indexOf("edge/")>0,G=(W&&W.indexOf("android"),W&&/iphone|ipad|ipod|ios/.test(W)||"ios"===z),Z=(W&&/chrome\/\d+/.test(W),W&&/phantomjs/.test(W),W&&W.match(/firefox\/(\d+)/)),J={}.watch,Q=!1;if(V)try{var Y={};Object.defineProperty(Y,"passive",{get:function(){Q=!0}}),window.addEventListener("test-passive",null,Y)}catch(t){}var tt=function(){return void 0===R&&(R=!V&&!H&&void 0!==t.g&&t.g.process&&"server"===t.g.process.env.VUE_ENV),R},et=V&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function nt(t){return"function"==typeof t&&/native code/.test(t.toString())}var rt,ot="undefined"!=typeof Symbol&&nt(Symbol)&&"undefined"!=typeof Reflect&&nt(Reflect.ownKeys);rt="undefined"!=typeof Set&&nt(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var it=S,at=0,st=function(){this.id=at++,this.subs=[]};st.prototype.addSub=function(t){this.subs.push(t)},st.prototype.removeSub=function(t){h(this.subs,t)},st.prototype.depend=function(){st.target&&st.target.addDep(this)},st.prototype.notify=function(){for(var t=this.subs.slice(),e=0,n=t.length;e-1)if(i&&!y(o,"default"))a=!1;else if(""===a||a===$(t)){var c=Mt(String,o.type);(c<0||s0&&(ce((s=ue(s,(e||"")+"_"+a))[0])&&ce(u)&&(l[c]=vt(u.text+s[0].text),s.shift()),l.push.apply(l,s)):i(s)?ce(u)?l[c]=vt(u.text+s):""!==s&&l.push(vt(s)):ce(s)&&ce(u)?l[c]=vt(u.text+s.text):(o(t._isVList)&&r(s.tag)&&n(s.key)&&r(e)&&(s.key="__vlist"+e+"_"+a+"__"),l.push(s)));return l}function le(t,e){if(t){for(var n=Object.create(null),r=ot?Reflect.ownKeys(t):Object.keys(t),o=0;o0,a=t?!!t.$stable:!i,s=t&&t.$key;if(t){if(t._normalized)return t._normalized;if(a&&r&&r!==e&&s===r.$key&&!i&&!r.$hasNormal)return r;for(var c in o={},t)t[c]&&"$"!==c[0]&&(o[c]=ve(n,c,t[c]))}else o={};for(var u in n)u in o||(o[u]=he(n,u));return t&&Object.isExtensible(t)&&(t._normalized=o),M(o,"$stable",a),M(o,"$key",s),M(o,"$hasNormal",i),o}function ve(t,e,n){var r=function(){var t=arguments.length?n.apply(null,arguments):n({});return(t=t&&"object"==typeof t&&!Array.isArray(t)?[t]:se(t))&&(0===t.length||1===t.length&&t[0].isComment)?void 0:t};return n.proxy&&Object.defineProperty(t,e,{get:r,enumerable:!0,configurable:!0}),r}function he(t,e){return function(){return t[e]}}function me(t,e){var n,o,i,s,c;if(Array.isArray(t)||"string"==typeof t)for(n=new Array(t.length),o=0,i=t.length;odocument.createEvent("Event").timeStamp&&(un=function(){return ln.now()})}function fn(){var t,e;for(cn=un(),an=!0,en.sort((function(t,e){return t.id-e.id})),sn=0;snsn&&en[n].id>t.id;)n--;en.splice(n+1,0,t)}else en.push(t);on||(on=!0,Qt(fn))}}(this)},dn.prototype.run=function(){if(this.active){var t=this.get();if(t!==this.value||a(t)||this.deep){var e=this.value;if(this.value=t,this.user)try{this.cb.call(this.vm,t,e)}catch(t){Rt(t,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,t,e)}}},dn.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},dn.prototype.depend=function(){for(var t=this.deps.length;t--;)this.deps[t].depend()},dn.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||h(this.vm._watchers,this);for(var t=this.deps.length;t--;)this.deps[t].removeSub(this);this.active=!1}};var vn={enumerable:!0,configurable:!0,get:S,set:S};function hn(t,e,n){vn.get=function(){return this[e][n]},vn.set=function(t){this[e][n]=t},Object.defineProperty(t,n,vn)}var mn={lazy:!0};function yn(t,e,n){var r=!tt();"function"==typeof n?(vn.get=r?_n(e):gn(n),vn.set=S):(vn.get=n.get?r&&!1!==n.cache?_n(e):gn(n.get):S,vn.set=n.set||S),Object.defineProperty(t,e,vn)}function _n(t){return function(){var e=this._computedWatchers&&this._computedWatchers[t];if(e)return e.dirty&&e.evaluate(),st.target&&e.depend(),e.value}}function gn(t){return function(){return t.call(this,this)}}function bn(t,e,n,r){return c(n)&&(r=n,n=n.handler),"string"==typeof n&&(n=t[n]),t.$watch(e,n,r)}var Cn=0;function wn(t){var e=t.options;if(t.super){var n=wn(t.super);if(n!==t.superOptions){t.superOptions=n;var r=function(t){var e,n=t.options,r=t.sealedOptions;for(var o in n)n[o]!==r[o]&&(e||(e={}),e[o]=n[o]);return e}(t);r&&O(t.extendOptions,r),(e=t.options=Dt(n,t.extendOptions)).name&&(e.components[e.name]=t)}}return e}function $n(t){this._init(t)}function An(t){return t&&(t.Ctor.options.name||t.tag)}function xn(t,e){return Array.isArray(t)?t.indexOf(e)>-1:"string"==typeof t?t.split(",").indexOf(e)>-1:(n=t,!("[object RegExp]"!==s.call(n))&&t.test(e));var n}function On(t,e){var n=t.cache,r=t.keys,o=t._vnode;for(var i in n){var a=n[i];if(a){var s=An(a.componentOptions);s&&!e(s)&&kn(n,i,r,o)}}}function kn(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),t[e]=null,h(n,e)}!function(t){t.prototype._init=function(t){var n=this;n._uid=Cn++,n._isVue=!0,t&&t._isComponent?function(t,e){var n=t.$options=Object.create(t.constructor.options),r=e._parentVnode;n.parent=e.parent,n._parentVnode=r;var o=r.componentOptions;n.propsData=o.propsData,n._parentListeners=o.listeners,n._renderChildren=o.children,n._componentTag=o.tag,e.render&&(n.render=e.render,n.staticRenderFns=e.staticRenderFns)}(n,t):n.$options=Dt(wn(n.constructor),t||{},n),n._renderProxy=n,n._self=n,function(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(t)}t.$parent=n,t.$root=n?n.$root:t,t.$children=[],t.$refs={},t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}(n),function(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t.$options._parentListeners;e&&Xe(t,e)}(n),function(t){t._vnode=null,t._staticTrees=null;var n=t.$options,r=t.$vnode=n._parentVnode,o=r&&r.context;t.$slots=fe(n._renderChildren,o),t.$scopedSlots=e,t._c=function(e,n,r,o){return Me(t,e,n,r,o,!1)},t.$createElement=function(e,n,r,o){return Me(t,e,n,r,o,!0)};var i=r&&r.data;$t(t,"$attrs",i&&i.attrs||e,null,!0),$t(t,"$listeners",n._parentListeners||e,null,!0)}(n),tn(n,"beforeCreate"),function(t){var e=le(t.$options.inject,t);e&&(bt(!1),Object.keys(e).forEach((function(n){$t(t,n,e[n])})),bt(!0))}(n),function(t){t._watchers=[];var e=t.$options;e.props&&function(t,e){var n=t.$options.propsData||{},r=t._props={},o=t.$options._propKeys=[];t.$parent&&bt(!1);var i=function(i){o.push(i);var a=Pt(i,e,n,t);$t(r,i,a),i in t||hn(t,"_props",i)};for(var a in e)i(a);bt(!0)}(t,e.props),e.methods&&function(t,e){for(var n in t.$options.props,e)t[n]="function"!=typeof e[n]?S:A(e[n],t)}(t,e.methods),e.data?function(t){var e=t.$options.data;c(e=t._data="function"==typeof e?function(t,e){ut();try{return t.call(e,e)}catch(t){return Rt(t,e,"data()"),{}}finally{lt()}}(e,t):e||{})||(e={});for(var n,r=Object.keys(e),o=t.$options.props,i=(t.$options.methods,r.length);i--;){var a=r[i];o&&y(o,a)||(n=void 0,36===(n=(a+"").charCodeAt(0))||95===n)||hn(t,"_data",a)}wt(e,!0)}(t):wt(t._data={},!0),e.computed&&function(t,e){var n=t._computedWatchers=Object.create(null),r=tt();for(var o in e){var i=e[o],a="function"==typeof i?i:i.get;r||(n[o]=new dn(t,a||S,S,mn)),o in t||yn(t,o,i)}}(t,e.computed),e.watch&&e.watch!==J&&function(t,e){for(var n in e){var r=e[n];if(Array.isArray(r))for(var o=0;o1?x(n):n;for(var r=x(arguments,1),o='event handler for "'+t+'"',i=0,a=n.length;iparseInt(this.max)&&kn(a,s[0],s,this._vnode)),e.data.keepAlive=!0}return e||t&&t[0]}}};!function(t){var e={get:function(){return F}};Object.defineProperty(t,"config",e),t.util={warn:it,extend:O,mergeOptions:Dt,defineReactive:$t},t.set=At,t.delete=xt,t.nextTick=Qt,t.observable=function(t){return wt(t),t},t.options=Object.create(null),P.forEach((function(e){t.options[e+"s"]=Object.create(null)})),t.options._base=t,O(t.options.components,En),function(t){t.use=function(t){var e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;var n=x(arguments,1);return n.unshift(this),"function"==typeof t.install?t.install.apply(t,n):"function"==typeof t&&t.apply(null,n),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=Dt(this.options,t),this}}(t),function(t){t.cid=0;var e=1;t.extend=function(t){t=t||{};var n=this,r=n.cid,o=t._Ctor||(t._Ctor={});if(o[r])return o[r];var i=t.name||n.options.name,a=function(t){this._init(t)};return(a.prototype=Object.create(n.prototype)).constructor=a,a.cid=e++,a.options=Dt(n.options,t),a.super=n,a.options.props&&function(t){var e=t.options.props;for(var n in e)hn(t.prototype,"_props",n)}(a),a.options.computed&&function(t){var e=t.options.computed;for(var n in e)yn(t.prototype,n,e[n])}(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,P.forEach((function(t){a[t]=n[t]})),i&&(a.options.components[i]=a),a.superOptions=n.options,a.extendOptions=t,a.sealedOptions=O({},a.options),o[r]=a,a}}(t),function(t){P.forEach((function(e){t[e]=function(t,n){return n?("component"===e&&c(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&"function"==typeof n&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}}))}(t)}($n),Object.defineProperty($n.prototype,"$isServer",{get:tt}),Object.defineProperty($n.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty($n,"FunctionalRenderContext",{value:Te}),$n.version="2.6.12";var jn=d("style,class"),Tn=d("input,textarea,option,select,progress"),In=d("contenteditable,draggable,spellcheck"),Dn=d("events,caret,typing,plaintext-only"),Nn=d("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),Pn="http://www.w3.org/1999/xlink",Ln=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},Fn=function(t){return Ln(t)?t.slice(6,t.length):""},Mn=function(t){return null==t||!1===t};function Rn(t,e){return{staticClass:Bn(t.staticClass,e.staticClass),class:r(t.class)?[t.class,e.class]:e.class}}function Bn(t,e){return t?e?t+" "+e:t:e||""}function Un(t){return Array.isArray(t)?function(t){for(var e,n="",o=0,i=t.length;o-1?lr(t,e,n):Nn(e)?Mn(n)?t.removeAttribute(e):(n="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,n)):In(e)?t.setAttribute(e,function(t,e){return Mn(e)||"false"===e?"false":"contenteditable"===t&&Dn(e)?e:"true"}(e,n)):Ln(e)?Mn(n)?t.removeAttributeNS(Pn,Fn(e)):t.setAttributeNS(Pn,e,n):lr(t,e,n)}function lr(t,e,n){if(Mn(n))t.removeAttribute(e);else{if(q&&!K&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==n&&!t.__ieph){var r=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",r)};t.addEventListener("input",r),t.__ieph=!0}t.setAttribute(e,n)}}var fr={create:cr,update:cr};function pr(t,e){var o=e.elm,i=e.data,a=t.data;if(!(n(i.staticClass)&&n(i.class)&&(n(a)||n(a.staticClass)&&n(a.class)))){var s=function(t){for(var e=t.data,n=t,o=t;r(o.componentInstance);)(o=o.componentInstance._vnode)&&o.data&&(e=Rn(o.data,e));for(;r(n=n.parent);)n&&n.data&&(e=Rn(e,n.data));return i=e.staticClass,a=e.class,r(i)||r(a)?Bn(i,Un(a)):"";var i,a}(e),c=o._transitionClasses;r(c)&&(s=Bn(s,Un(c))),s!==o._prevClass&&(o.setAttribute("class",s),o._prevClass=s)}}var dr,vr={create:pr,update:pr};function hr(t,e,n){var r=dr;return function o(){var i=e.apply(null,arguments);null!==i&&_r(t,o,n,r)}}var mr=zt&&!(Z&&Number(Z[1])<=53);function yr(t,e,n,r){if(mr){var o=cn,i=e;e=i._wrapper=function(t){if(t.target===t.currentTarget||t.timeStamp>=o||t.timeStamp<=0||t.target.ownerDocument!==document)return i.apply(this,arguments)}}dr.addEventListener(t,e,Q?{capture:n,passive:r}:n)}function _r(t,e,n,r){(r||dr).removeEventListener(t,e._wrapper||e,n)}function gr(t,e){if(!n(t.data.on)||!n(e.data.on)){var o=e.data.on||{},i=t.data.on||{};dr=e.elm,function(t){if(r(t.__r)){var e=q?"change":"input";t[e]=[].concat(t.__r,t[e]||[]),delete t.__r}r(t.__c)&&(t.change=[].concat(t.__c,t.change||[]),delete t.__c)}(o),oe(o,i,yr,_r,hr,e.context),dr=void 0}}var br,Cr={create:gr,update:gr};function wr(t,e){if(!n(t.data.domProps)||!n(e.data.domProps)){var o,i,a=e.elm,s=t.data.domProps||{},c=e.data.domProps||{};for(o in r(c.__ob__)&&(c=e.data.domProps=O({},c)),s)o in c||(a[o]="");for(o in c){if(i=c[o],"textContent"===o||"innerHTML"===o){if(e.children&&(e.children.length=0),i===s[o])continue;1===a.childNodes.length&&a.removeChild(a.childNodes[0])}if("value"===o&&"PROGRESS"!==a.tagName){a._value=i;var u=n(i)?"":String(i);$r(a,u)&&(a.value=u)}else if("innerHTML"===o&&zn(a.tagName)&&n(a.innerHTML)){(br=br||document.createElement("div")).innerHTML=""+i+"";for(var l=br.firstChild;a.firstChild;)a.removeChild(a.firstChild);for(;l.firstChild;)a.appendChild(l.firstChild)}else if(i!==s[o])try{a[o]=i}catch(t){}}}}function $r(t,e){return!t.composing&&("OPTION"===t.tagName||function(t,e){var n=!0;try{n=document.activeElement!==t}catch(t){}return n&&t.value!==e}(t,e)||function(t,e){var n=t.value,o=t._vModifiers;if(r(o)){if(o.number)return p(n)!==p(e);if(o.trim)return n.trim()!==e.trim()}return n!==e}(t,e))}var Ar={create:wr,update:wr},xr=_((function(t){var e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach((function(t){if(t){var r=t.split(n);r.length>1&&(e[r[0].trim()]=r[1].trim())}})),e}));function Or(t){var e=kr(t.style);return t.staticStyle?O(t.staticStyle,e):e}function kr(t){return Array.isArray(t)?k(t):"string"==typeof t?xr(t):t}var Sr,Er=/^--/,jr=/\s*!important$/,Tr=function(t,e,n){if(Er.test(e))t.style.setProperty(e,n);else if(jr.test(n))t.style.setProperty($(e),n.replace(jr,""),"important");else{var r=Dr(e);if(Array.isArray(n))for(var o=0,i=n.length;o-1?e.split(Lr).forEach((function(e){return t.classList.add(e)})):t.classList.add(e);else{var n=" "+(t.getAttribute("class")||"")+" ";n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function Mr(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(Lr).forEach((function(e){return t.classList.remove(e)})):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var n=" "+(t.getAttribute("class")||"")+" ",r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?t.setAttribute("class",n):t.removeAttribute("class")}}function Rr(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&O(e,Br(t.name||"v")),O(e,t),e}return"string"==typeof t?Br(t):void 0}}var Br=_((function(t){return{enterClass:t+"-enter",enterToClass:t+"-enter-to",enterActiveClass:t+"-enter-active",leaveClass:t+"-leave",leaveToClass:t+"-leave-to",leaveActiveClass:t+"-leave-active"}})),Ur=V&&!K,Vr="transition",Hr="animation",zr="transition",Wr="transitionend",qr="animation",Kr="animationend";Ur&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(zr="WebkitTransition",Wr="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(qr="WebkitAnimation",Kr="webkitAnimationEnd"));var Xr=V?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(t){return t()};function Gr(t){Xr((function(){Xr(t)}))}function Zr(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),Fr(t,e))}function Jr(t,e){t._transitionClasses&&h(t._transitionClasses,e),Mr(t,e)}function Qr(t,e,n){var r=to(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s=o===Vr?Wr:Kr,c=0,u=function(){t.removeEventListener(s,l),n()},l=function(e){e.target===t&&++c>=a&&u()};setTimeout((function(){c0&&(n=Vr,l=a,f=i.length):e===Hr?u>0&&(n=Hr,l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?Vr:Hr:null)?n===Vr?i.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:n===Vr&&Yr.test(r[zr+"Property"])}}function eo(t,e){for(;t.length1}function so(t,e){!0!==e.data.show&&ro(e)}var co=function(t){var e,a,s={},c=t.modules,u=t.nodeOps;for(e=0;ev?g(t,n(o[y+1])?null:o[y+1].elm,o,d,y,i):d>y&&C(e,p,v)}(p,h,y,i,l):r(y)?(r(t.text)&&u.setTextContent(p,""),g(p,null,y,0,y.length-1,i)):r(h)?C(h,0,h.length-1):r(t.text)&&u.setTextContent(p,""):t.text!==e.text&&u.setTextContent(p,e.text),r(v)&&r(d=v.hook)&&r(d=d.postpatch)&&d(t,e)}}}function x(t,e,n){if(o(n)&&r(t.parent))t.parent.data.pendingInsert=e;else for(var i=0;i-1,a.selected!==i&&(a.selected=i);else if(T(vo(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));o||(t.selectedIndex=-1)}}function po(t,e){return e.every((function(e){return!T(e,t)}))}function vo(t){return"_value"in t?t._value:t.value}function ho(t){t.target.composing=!0}function mo(t){t.target.composing&&(t.target.composing=!1,yo(t.target,"input"))}function yo(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function _o(t){return!t.componentInstance||t.data&&t.data.transition?t:_o(t.componentInstance._vnode)}var go={model:uo,show:{bind:function(t,e,n){var r=e.value,o=(n=_o(n)).data&&n.data.transition,i=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;r&&o?(n.data.show=!0,ro(n,(function(){t.style.display=i}))):t.style.display=r?i:"none"},update:function(t,e,n){var r=e.value;!r!=!e.oldValue&&((n=_o(n)).data&&n.data.transition?(n.data.show=!0,r?ro(n,(function(){t.style.display=t.__vOriginalDisplay})):oo(n,(function(){t.style.display="none"}))):t.style.display=r?t.__vOriginalDisplay:"none")},unbind:function(t,e,n,r,o){o||(t.style.display=t.__vOriginalDisplay)}}},bo={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function Co(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?Co(ze(e.children)):t}function wo(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];var o=n._parentListeners;for(var i in o)e[b(i)]=o[i];return e}function $o(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}var Ao=function(t){return t.tag||He(t)},xo=function(t){return"show"===t.name},Oo={name:"transition",props:bo,abstract:!0,render:function(t){var e=this,n=this.$slots.default;if(n&&(n=n.filter(Ao)).length){var r=this.mode,o=n[0];if(function(t){for(;t=t.parent;)if(t.data.transition)return!0}(this.$vnode))return o;var a=Co(o);if(!a)return o;if(this._leaving)return $o(t,o);var s="__transition-"+this._uid+"-";a.key=null==a.key?a.isComment?s+"comment":s+a.tag:i(a.key)?0===String(a.key).indexOf(s)?a.key:s+a.key:a.key;var c=(a.data||(a.data={})).transition=wo(this),u=this._vnode,l=Co(u);if(a.data.directives&&a.data.directives.some(xo)&&(a.data.show=!0),l&&l.data&&!function(t,e){return e.key===t.key&&e.tag===t.tag}(a,l)&&!He(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=O({},c);if("out-in"===r)return this._leaving=!0,ie(f,"afterLeave",(function(){e._leaving=!1,e.$forceUpdate()})),$o(t,o);if("in-out"===r){if(He(a))return u;var p,d=function(){p()};ie(c,"afterEnter",d),ie(c,"enterCancelled",d),ie(f,"delayLeave",(function(t){p=t}))}}return o}}},ko=O({tag:String,moveClass:String},bo);function So(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._enterCb()}function Eo(t){t.data.newPos=t.elm.getBoundingClientRect()}function jo(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-n.top;if(r||o){t.data.moved=!0;var i=t.elm.style;i.transform=i.WebkitTransform="translate("+r+"px,"+o+"px)",i.transitionDuration="0s"}}delete ko.mode;var To={Transition:Oo,TransitionGroup:{props:ko,beforeMount:function(){var t=this,e=this._update;this._update=function(n,r){var o=Ze(t);t.__patch__(t._vnode,t.kept,!1,!0),t._vnode=t.kept,o(),e.call(t,n,r)}},render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],a=wo(this),s=0;s-1?qn[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:qn[t]=/HTMLUnknownElement/.test(e.toString())},O($n.options.directives,go),O($n.options.components,To),$n.prototype.__patch__=V?co:S,$n.prototype.$mount=function(t,e){return function(t,e,n){var r;return t.$el=e,t.$options.render||(t.$options.render=dt),tn(t,"beforeMount"),r=function(){t._update(t._render(),n)},new dn(t,r,S,{before:function(){t._isMounted&&!t._isDestroyed&&tn(t,"beforeUpdate")}},!0),n=!1,null==t.$vnode&&(t._isMounted=!0,tn(t,"mounted")),t}(this,t=t&&V?function(t){return"string"==typeof t?document.querySelector(t)||document.createElement("div"):t}(t):void 0,e)},V&&setTimeout((function(){F.devtools&&et&&et.emit("init",$n)}),0);const Io=$n;var Do=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("section",{attrs:{id:"app"}},[n("h1",[t._v("我去")]),t._v(" "),n("Foo"),t._v(" "),n("Bar")],1)};Do._withStripped=!0;var No=function(){var t=this;t.$createElement;return t._self._c,t._m(0)};function Po(t,e,n,r,o,i,a,s){var c,u="function"==typeof t?t.options:t;if(e&&(u.render=e,u.staticRenderFns=n,u._compiled=!0),r&&(u.functional=!0),i&&(u._scopeId="data-v-"+i),a?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),o&&o.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(a)},u._ssrRegister=c):o&&(c=s?function(){o.call(this,(u.functional?this.parent:this).$root.$options.shadowRoot)}:o),c)if(u.functional){u._injectStyles=c;var l=u.render;u.render=function(t,e){return c.call(e),l(t,e)}}else{var f=u.beforeCreate;u.beforeCreate=f?[].concat(f,c):[c]}return{exports:t,options:u}}No._withStripped=!0;var Lo=Po({name:"bar",data:function(){return{}},components:{},watch:{},mounted:function(){},methods:{}},No,[function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("section",{staticClass:"bar"},[n("h1",[t._v("Bar")])])}],!1,null,"2aa73eda",null);Lo.options.__file="src/components/Bar.vue";const Fo=Lo.exports;var Mo=function(){var t=this;t.$createElement;return t._self._c,t._m(0)};Mo._withStripped=!0;var Ro=Po({name:"Foo",data:function(){return{}},components:{},watch:{},mounted:function(){},methods:{}},Mo,[function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("section",{staticClass:"foo"},[n("h1",[t._v("Foo")])])}],!1,null,"54024074",null);Ro.options.__file="src/components/Foo.vue";var Bo=Po({name:"app",data:function(){return{}},components:{Foo:Ro.exports,Bar:Fo},watch:{},mounted:function(){},methods:{}},Do,[],!1,null,null,null);Bo.options.__file="src/App.vue";const Uo=Bo.exports;new Io({el:"#app",data:{},render:function(t){return t(Uo)}})})(); 3 | //# sourceMappingURL=bundle.js.map -------------------------------------------------------------------------------- /SSR-1/dist/server.bundle.js: -------------------------------------------------------------------------------- 1 | /*! For license information please see server.bundle.js.LICENSE.txt */ 2 | module.exports=(()=>{var t={241:(t,e,n)=>{"use strict";n.r(e),n.d(e,{default:()=>zo});var r=Object.freeze({});function o(t){return null==t}function i(t){return null!=t}function a(t){return!0===t}function s(t){return"string"==typeof t||"number"==typeof t||"symbol"==typeof t||"boolean"==typeof t}function c(t){return null!==t&&"object"==typeof t}var u=Object.prototype.toString;function l(t){return"[object Object]"===u.call(t)}function f(t){var e=parseFloat(String(t));return e>=0&&Math.floor(e)===e&&isFinite(t)}function d(t){return i(t)&&"function"==typeof t.then&&"function"==typeof t.catch}function p(t){return null==t?"":Array.isArray(t)||l(t)&&t.toString===u?JSON.stringify(t,null,2):String(t)}function v(t){var e=parseFloat(t);return isNaN(e)?t:e}function h(t,e){for(var n=Object.create(null),r=t.split(","),o=0;o-1)return t.splice(n,1)}}var _=Object.prototype.hasOwnProperty;function g(t,e){return _.call(t,e)}function b(t){var e=Object.create(null);return function(n){return e[n]||(e[n]=t(n))}}var C=/-(\w)/g,w=b((function(t){return t.replace(C,(function(t,e){return e?e.toUpperCase():""}))})),$=b((function(t){return t.charAt(0).toUpperCase()+t.slice(1)})),x=/\B([A-Z])/g,A=b((function(t){return t.replace(x,"-$1").toLowerCase()})),O=Function.prototype.bind?function(t,e){return t.bind(e)}:function(t,e){function n(n){var r=arguments.length;return r?r>1?t.apply(e,arguments):t.call(e,n):t.call(e)}return n._length=t.length,n};function k(t,e){e=e||0;for(var n=t.length-e,r=new Array(n);n--;)r[n]=t[n+e];return r}function S(t,e){for(var n in e)t[n]=e[n];return t}function j(t){for(var e={},n=0;n0,G=X&&X.indexOf("edge/")>0,J=(X&&X.indexOf("android"),X&&/iphone|ipad|ipod|ios/.test(X)||"ios"===q),Q=(X&&/chrome\/\d+/.test(X),X&&/phantomjs/.test(X),X&&X.match(/firefox\/(\d+)/)),Y={}.watch,tt=!1;if(z)try{var et={};Object.defineProperty(et,"passive",{get:function(){tt=!0}}),window.addEventListener("test-passive",null,et)}catch(t){}var nt=function(){return void 0===B&&(B=!z&&!W&&"undefined"!=typeof global&&global.process&&"server"===global.process.env.VUE_ENV),B},rt=z&&window.__VUE_DEVTOOLS_GLOBAL_HOOK__;function ot(t){return"function"==typeof t&&/native code/.test(t.toString())}var it,at="undefined"!=typeof Symbol&&ot(Symbol)&&"undefined"!=typeof Reflect&&ot(Reflect.ownKeys);it="undefined"!=typeof Set&&ot(Set)?Set:function(){function t(){this.set=Object.create(null)}return t.prototype.has=function(t){return!0===this.set[t]},t.prototype.add=function(t){this.set[t]=!0},t.prototype.clear=function(){this.set=Object.create(null)},t}();var st=E,ct=0,ut=function(){this.id=ct++,this.subs=[]};ut.prototype.addSub=function(t){this.subs.push(t)},ut.prototype.removeSub=function(t){y(this.subs,t)},ut.prototype.depend=function(){ut.target&&ut.target.addDep(this)},ut.prototype.notify=function(){for(var t=this.subs.slice(),e=0,n=t.length;e-1)if(i&&!g(o,"default"))a=!1;else if(""===a||a===A(t)){var c=Ut(String,o.type);(c<0||s0&&(le((r=fe(r,(e||"")+"_"+n))[0])&&le(u)&&(l[c]=mt(u.text+r[0].text),r.shift()),l.push.apply(l,r)):s(r)?le(u)?l[c]=mt(u.text+r):""!==r&&l.push(mt(r)):le(r)&&le(u)?l[c]=mt(u.text+r.text):(a(t._isVList)&&i(r.tag)&&o(r.key)&&i(e)&&(r.key="__vlist"+e+"_"+n+"__"),l.push(r)));return l}function de(t,e){if(t){for(var n=Object.create(null),r=at?Reflect.ownKeys(t):Object.keys(t),o=0;o0,a=t?!!t.$stable:!i,s=t&&t.$key;if(t){if(t._normalized)return t._normalized;if(a&&n&&n!==r&&s===n.$key&&!i&&!n.$hasNormal)return n;for(var c in o={},t)t[c]&&"$"!==c[0]&&(o[c]=me(e,c,t[c]))}else o={};for(var u in e)u in o||(o[u]=ye(e,u));return t&&Object.isExtensible(t)&&(t._normalized=o),U(o,"$stable",a),U(o,"$key",s),U(o,"$hasNormal",i),o}function me(t,e,n){var r=function(){var t=arguments.length?n.apply(null,arguments):n({});return(t=t&&"object"==typeof t&&!Array.isArray(t)?[t]:ue(t))&&(0===t.length||1===t.length&&t[0].isComment)?void 0:t};return n.proxy&&Object.defineProperty(t,e,{get:r,enumerable:!0,configurable:!0}),r}function ye(t,e){return function(){return t[e]}}function _e(t,e){var n,r,o,a,s;if(Array.isArray(t)||"string"==typeof t)for(n=new Array(t.length),r=0,o=t.length;rdocument.createEvent("Event").timeStamp&&(fn=function(){return dn.now()})}function pn(){var t,e;for(ln=fn(),cn=!0,rn.sort((function(t,e){return t.id-e.id})),un=0;unun&&rn[n].id>t.id;)n--;rn.splice(n+1,0,t)}else rn.push(t);sn||(sn=!0,te(pn))}}(this)},hn.prototype.run=function(){if(this.active){var t=this.get();if(t!==this.value||c(t)||this.deep){var e=this.value;if(this.value=t,this.user)try{this.cb.call(this.vm,t,e)}catch(t){Bt(t,this.vm,'callback for watcher "'+this.expression+'"')}else this.cb.call(this.vm,t,e)}}},hn.prototype.evaluate=function(){this.value=this.get(),this.dirty=!1},hn.prototype.depend=function(){for(var t=this.deps.length;t--;)this.deps[t].depend()},hn.prototype.teardown=function(){if(this.active){this.vm._isBeingDestroyed||y(this.vm._watchers,this);for(var t=this.deps.length;t--;)this.deps[t].removeSub(this);this.active=!1}};var mn={enumerable:!0,configurable:!0,get:E,set:E};function yn(t,e,n){mn.get=function(){return this[e][n]},mn.set=function(t){this[e][n]=t},Object.defineProperty(t,n,mn)}var _n={lazy:!0};function gn(t,e,n){var r=!nt();"function"==typeof n?(mn.get=r?bn(e):Cn(n),mn.set=E):(mn.get=n.get?r&&!1!==n.cache?bn(e):Cn(n.get):E,mn.set=n.set||E),Object.defineProperty(t,e,mn)}function bn(t){return function(){var e=this._computedWatchers&&this._computedWatchers[t];if(e)return e.dirty&&e.evaluate(),ut.target&&e.depend(),e.value}}function Cn(t){return function(){return t.call(this,this)}}function wn(t,e,n,r){return l(n)&&(r=n,n=n.handler),"string"==typeof n&&(n=t[n]),t.$watch(e,n,r)}var $n=0;function xn(t){var e=t.options;if(t.super){var n=xn(t.super);if(n!==t.superOptions){t.superOptions=n;var r=function(t){var e,n=t.options,r=t.sealedOptions;for(var o in n)n[o]!==r[o]&&(e||(e={}),e[o]=n[o]);return e}(t);r&&S(t.extendOptions,r),(e=t.options=Pt(n,t.extendOptions)).name&&(e.components[e.name]=t)}}return e}function An(t){this._init(t)}function On(t){return t&&(t.Ctor.options.name||t.tag)}function kn(t,e){return Array.isArray(t)?t.indexOf(e)>-1:"string"==typeof t?t.split(",").indexOf(e)>-1:(n=t,!("[object RegExp]"!==u.call(n))&&t.test(e));var n}function Sn(t,e){var n=t.cache,r=t.keys,o=t._vnode;for(var i in n){var a=n[i];if(a){var s=On(a.componentOptions);s&&!e(s)&&jn(n,i,r,o)}}}function jn(t,e,n,r){var o=t[e];!o||r&&o.tag===r.tag||o.componentInstance.$destroy(),t[e]=null,y(n,e)}!function(t){t.prototype._init=function(t){var e=this;e._uid=$n++,e._isVue=!0,t&&t._isComponent?function(t,e){var n=t.$options=Object.create(t.constructor.options),r=e._parentVnode;n.parent=e.parent,n._parentVnode=r;var o=r.componentOptions;n.propsData=o.propsData,n._parentListeners=o.listeners,n._renderChildren=o.children,n._componentTag=o.tag,e.render&&(n.render=e.render,n.staticRenderFns=e.staticRenderFns)}(e,t):e.$options=Pt(xn(e.constructor),t||{},e),e._renderProxy=e,e._self=e,function(t){var e=t.$options,n=e.parent;if(n&&!e.abstract){for(;n.$options.abstract&&n.$parent;)n=n.$parent;n.$children.push(t)}t.$parent=n,t.$root=n?n.$root:t,t.$children=[],t.$refs={},t._watcher=null,t._inactive=null,t._directInactive=!1,t._isMounted=!1,t._isDestroyed=!1,t._isBeingDestroyed=!1}(e),function(t){t._events=Object.create(null),t._hasHookEvent=!1;var e=t.$options._parentListeners;e&&Ge(t,e)}(e),function(t){t._vnode=null,t._staticTrees=null;var e=t.$options,n=t.$vnode=e._parentVnode,o=n&&n.context;t.$slots=pe(e._renderChildren,o),t.$scopedSlots=r,t._c=function(e,n,r,o){return Ue(t,e,n,r,o,!1)},t.$createElement=function(e,n,r,o){return Ue(t,e,n,r,o,!0)};var i=n&&n.data;At(t,"$attrs",i&&i.attrs||r,null,!0),At(t,"$listeners",e._parentListeners||r,null,!0)}(e),nn(e,"beforeCreate"),function(t){var e=de(t.$options.inject,t);e&&(wt(!1),Object.keys(e).forEach((function(n){At(t,n,e[n])})),wt(!0))}(e),function(t){t._watchers=[];var e=t.$options;e.props&&function(t,e){var n=t.$options.propsData||{},r=t._props={},o=t.$options._propKeys=[];t.$parent&&wt(!1);var i=function(i){o.push(i);var a=Lt(i,e,n,t);At(r,i,a),i in t||yn(t,"_props",i)};for(var a in e)i(a);wt(!0)}(t,e.props),e.methods&&function(t,e){for(var n in t.$options.props,e)t[n]="function"!=typeof e[n]?E:O(e[n],t)}(t,e.methods),e.data?function(t){var e=t.$options.data;l(e=t._data="function"==typeof e?function(t,e){ft();try{return t.call(e,e)}catch(t){return Bt(t,e,"data()"),{}}finally{dt()}}(e,t):e||{})||(e={});for(var n,r=Object.keys(e),o=t.$options.props,i=(t.$options.methods,r.length);i--;){var a=r[i];o&&g(o,a)||(n=void 0,36===(n=(a+"").charCodeAt(0))||95===n)||yn(t,"_data",a)}xt(e,!0)}(t):xt(t._data={},!0),e.computed&&function(t,e){var n=t._computedWatchers=Object.create(null),r=nt();for(var o in e){var i=e[o],a="function"==typeof i?i:i.get;r||(n[o]=new hn(t,a||E,E,_n)),o in t||gn(t,o,i)}}(t,e.computed),e.watch&&e.watch!==Y&&function(t,e){for(var n in e){var r=e[n];if(Array.isArray(r))for(var o=0;o1?k(n):n;for(var r=k(arguments,1),o='event handler for "'+t+'"',i=0,a=n.length;iparseInt(this.max)&&jn(a,s[0],s,this._vnode)),e.data.keepAlive=!0}return e||t&&t[0]}}};!function(t){var e={get:function(){return R}};Object.defineProperty(t,"config",e),t.util={warn:st,extend:S,mergeOptions:Pt,defineReactive:At},t.set=Ot,t.delete=kt,t.nextTick=te,t.observable=function(t){return xt(t),t},t.options=Object.create(null),L.forEach((function(e){t.options[e+"s"]=Object.create(null)})),t.options._base=t,S(t.options.components,Tn),function(t){t.use=function(t){var e=this._installedPlugins||(this._installedPlugins=[]);if(e.indexOf(t)>-1)return this;var n=k(arguments,1);return n.unshift(this),"function"==typeof t.install?t.install.apply(t,n):"function"==typeof t&&t.apply(null,n),e.push(t),this}}(t),function(t){t.mixin=function(t){return this.options=Pt(this.options,t),this}}(t),function(t){t.cid=0;var e=1;t.extend=function(t){t=t||{};var n=this,r=n.cid,o=t._Ctor||(t._Ctor={});if(o[r])return o[r];var i=t.name||n.options.name,a=function(t){this._init(t)};return(a.prototype=Object.create(n.prototype)).constructor=a,a.cid=e++,a.options=Pt(n.options,t),a.super=n,a.options.props&&function(t){var e=t.options.props;for(var n in e)yn(t.prototype,"_props",n)}(a),a.options.computed&&function(t){var e=t.options.computed;for(var n in e)gn(t.prototype,n,e[n])}(a),a.extend=n.extend,a.mixin=n.mixin,a.use=n.use,L.forEach((function(t){a[t]=n[t]})),i&&(a.options.components[i]=a),a.superOptions=n.options,a.extendOptions=t,a.sealedOptions=S({},a.options),o[r]=a,a}}(t),function(t){L.forEach((function(e){t[e]=function(t,n){return n?("component"===e&&l(n)&&(n.name=n.name||t,n=this.options._base.extend(n)),"directive"===e&&"function"==typeof n&&(n={bind:n,update:n}),this.options[e+"s"][t]=n,n):this.options[e+"s"][t]}}))}(t)}(An),Object.defineProperty(An.prototype,"$isServer",{get:nt}),Object.defineProperty(An.prototype,"$ssrContext",{get:function(){return this.$vnode&&this.$vnode.ssrContext}}),Object.defineProperty(An,"FunctionalRenderContext",{value:De}),An.version="2.6.12";var In=h("style,class"),Dn=h("input,textarea,option,select,progress"),Nn=h("contenteditable,draggable,spellcheck"),Pn=h("events,caret,typing,plaintext-only"),Mn=h("allowfullscreen,async,autofocus,autoplay,checked,compact,controls,declare,default,defaultchecked,defaultmuted,defaultselected,defer,disabled,enabled,formnovalidate,hidden,indeterminate,inert,ismap,itemscope,loop,multiple,muted,nohref,noresize,noshade,novalidate,nowrap,open,pauseonexit,readonly,required,reversed,scoped,seamless,selected,sortable,translate,truespeed,typemustmatch,visible"),Ln="http://www.w3.org/1999/xlink",Fn=function(t){return":"===t.charAt(5)&&"xlink"===t.slice(0,5)},Rn=function(t){return Fn(t)?t.slice(6,t.length):""},Un=function(t){return null==t||!1===t};function Bn(t,e){return{staticClass:Vn(t.staticClass,e.staticClass),class:i(t.class)?[t.class,e.class]:e.class}}function Vn(t,e){return t?e?t+" "+e:t:e||""}function Hn(t){return Array.isArray(t)?function(t){for(var e,n="",r=0,o=t.length;r-1?dr(t,e,n):Mn(e)?Un(n)?t.removeAttribute(e):(n="allowfullscreen"===e&&"EMBED"===t.tagName?"true":e,t.setAttribute(e,n)):Nn(e)?t.setAttribute(e,function(t,e){return Un(e)||"false"===e?"false":"contenteditable"===t&&Pn(e)?e:"true"}(e,n)):Fn(e)?Un(n)?t.removeAttributeNS(Ln,Rn(e)):t.setAttributeNS(Ln,e,n):dr(t,e,n)}function dr(t,e,n){if(Un(n))t.removeAttribute(e);else{if(K&&!Z&&"TEXTAREA"===t.tagName&&"placeholder"===e&&""!==n&&!t.__ieph){var r=function(e){e.stopImmediatePropagation(),t.removeEventListener("input",r)};t.addEventListener("input",r),t.__ieph=!0}t.setAttribute(e,n)}}var pr={create:lr,update:lr};function vr(t,e){var n=e.elm,r=e.data,a=t.data;if(!(o(r.staticClass)&&o(r.class)&&(o(a)||o(a.staticClass)&&o(a.class)))){var s=function(t){for(var e=t.data,n=t,r=t;i(r.componentInstance);)(r=r.componentInstance._vnode)&&r.data&&(e=Bn(r.data,e));for(;i(n=n.parent);)n&&n.data&&(e=Bn(e,n.data));return o=e.staticClass,a=e.class,i(o)||i(a)?Vn(o,Hn(a)):"";var o,a}(e),c=n._transitionClasses;i(c)&&(s=Vn(s,Hn(c))),s!==n._prevClass&&(n.setAttribute("class",s),n._prevClass=s)}}var hr,mr={create:vr,update:vr};function yr(t,e,n){var r=hr;return function o(){var i=e.apply(null,arguments);null!==i&&br(t,o,n,r)}}var _r=qt&&!(Q&&Number(Q[1])<=53);function gr(t,e,n,r){if(_r){var o=ln,i=e;e=i._wrapper=function(t){if(t.target===t.currentTarget||t.timeStamp>=o||t.timeStamp<=0||t.target.ownerDocument!==document)return i.apply(this,arguments)}}hr.addEventListener(t,e,tt?{capture:n,passive:r}:n)}function br(t,e,n,r){(r||hr).removeEventListener(t,e._wrapper||e,n)}function Cr(t,e){if(!o(t.data.on)||!o(e.data.on)){var n=e.data.on||{},r=t.data.on||{};hr=e.elm,function(t){if(i(t.__r)){var e=K?"change":"input";t[e]=[].concat(t.__r,t[e]||[]),delete t.__r}i(t.__c)&&(t.change=[].concat(t.__c,t.change||[]),delete t.__c)}(n),ae(n,r,gr,br,yr,e.context),hr=void 0}}var wr,$r={create:Cr,update:Cr};function xr(t,e){if(!o(t.data.domProps)||!o(e.data.domProps)){var n,r,a=e.elm,s=t.data.domProps||{},c=e.data.domProps||{};for(n in i(c.__ob__)&&(c=e.data.domProps=S({},c)),s)n in c||(a[n]="");for(n in c){if(r=c[n],"textContent"===n||"innerHTML"===n){if(e.children&&(e.children.length=0),r===s[n])continue;1===a.childNodes.length&&a.removeChild(a.childNodes[0])}if("value"===n&&"PROGRESS"!==a.tagName){a._value=r;var u=o(r)?"":String(r);Ar(a,u)&&(a.value=u)}else if("innerHTML"===n&&qn(a.tagName)&&o(a.innerHTML)){(wr=wr||document.createElement("div")).innerHTML=""+r+"";for(var l=wr.firstChild;a.firstChild;)a.removeChild(a.firstChild);for(;l.firstChild;)a.appendChild(l.firstChild)}else if(r!==s[n])try{a[n]=r}catch(t){}}}}function Ar(t,e){return!t.composing&&("OPTION"===t.tagName||function(t,e){var n=!0;try{n=document.activeElement!==t}catch(t){}return n&&t.value!==e}(t,e)||function(t,e){var n=t.value,r=t._vModifiers;if(i(r)){if(r.number)return v(n)!==v(e);if(r.trim)return n.trim()!==e.trim()}return n!==e}(t,e))}var Or={create:xr,update:xr},kr=b((function(t){var e={},n=/:(.+)/;return t.split(/;(?![^(]*\))/g).forEach((function(t){if(t){var r=t.split(n);r.length>1&&(e[r[0].trim()]=r[1].trim())}})),e}));function Sr(t){var e=jr(t.style);return t.staticStyle?S(t.staticStyle,e):e}function jr(t){return Array.isArray(t)?j(t):"string"==typeof t?kr(t):t}var Er,Tr=/^--/,Ir=/\s*!important$/,Dr=function(t,e,n){if(Tr.test(e))t.style.setProperty(e,n);else if(Ir.test(n))t.style.setProperty(A(e),n.replace(Ir,""),"important");else{var r=Pr(e);if(Array.isArray(n))for(var o=0,i=n.length;o-1?e.split(Fr).forEach((function(e){return t.classList.add(e)})):t.classList.add(e);else{var n=" "+(t.getAttribute("class")||"")+" ";n.indexOf(" "+e+" ")<0&&t.setAttribute("class",(n+e).trim())}}function Ur(t,e){if(e&&(e=e.trim()))if(t.classList)e.indexOf(" ")>-1?e.split(Fr).forEach((function(e){return t.classList.remove(e)})):t.classList.remove(e),t.classList.length||t.removeAttribute("class");else{for(var n=" "+(t.getAttribute("class")||"")+" ",r=" "+e+" ";n.indexOf(r)>=0;)n=n.replace(r," ");(n=n.trim())?t.setAttribute("class",n):t.removeAttribute("class")}}function Br(t){if(t){if("object"==typeof t){var e={};return!1!==t.css&&S(e,Vr(t.name||"v")),S(e,t),e}return"string"==typeof t?Vr(t):void 0}}var Vr=b((function(t){return{enterClass:t+"-enter",enterToClass:t+"-enter-to",enterActiveClass:t+"-enter-active",leaveClass:t+"-leave",leaveToClass:t+"-leave-to",leaveActiveClass:t+"-leave-active"}})),Hr=z&&!Z,zr="transition",Wr="animation",qr="transition",Xr="transitionend",Kr="animation",Zr="animationend";Hr&&(void 0===window.ontransitionend&&void 0!==window.onwebkittransitionend&&(qr="WebkitTransition",Xr="webkitTransitionEnd"),void 0===window.onanimationend&&void 0!==window.onwebkitanimationend&&(Kr="WebkitAnimation",Zr="webkitAnimationEnd"));var Gr=z?window.requestAnimationFrame?window.requestAnimationFrame.bind(window):setTimeout:function(t){return t()};function Jr(t){Gr((function(){Gr(t)}))}function Qr(t,e){var n=t._transitionClasses||(t._transitionClasses=[]);n.indexOf(e)<0&&(n.push(e),Rr(t,e))}function Yr(t,e){t._transitionClasses&&y(t._transitionClasses,e),Ur(t,e)}function to(t,e,n){var r=no(t,e),o=r.type,i=r.timeout,a=r.propCount;if(!o)return n();var s=o===zr?Xr:Zr,c=0,u=function(){t.removeEventListener(s,l),n()},l=function(e){e.target===t&&++c>=a&&u()};setTimeout((function(){c0&&(n=zr,l=a,f=i.length):e===Wr?u>0&&(n=Wr,l=u,f=c.length):f=(n=(l=Math.max(a,u))>0?a>u?zr:Wr:null)?n===zr?i.length:c.length:0,{type:n,timeout:l,propCount:f,hasTransform:n===zr&&eo.test(r[qr+"Property"])}}function ro(t,e){for(;t.length1}function uo(t,e){!0!==e.data.show&&io(e)}var lo=function(t){var e,n,r={},c=t.modules,u=t.nodeOps;for(e=0;ev?g(t,o(n[y+1])?null:n[y+1].elm,n,p,y,r):p>y&&C(e,d,v)}(d,h,y,n,l):i(y)?(i(t.text)&&u.setTextContent(d,""),g(d,null,y,0,y.length-1,n)):i(h)?C(h,0,h.length-1):i(t.text)&&u.setTextContent(d,""):t.text!==e.text&&u.setTextContent(d,e.text),i(v)&&i(p=v.hook)&&i(p=p.postpatch)&&p(t,e)}}}function A(t,e,n){if(a(n)&&i(t.parent))t.parent.data.pendingInsert=e;else for(var r=0;r-1,a.selected!==i&&(a.selected=i);else if(D(mo(a),r))return void(t.selectedIndex!==s&&(t.selectedIndex=s));o||(t.selectedIndex=-1)}}function ho(t,e){return e.every((function(e){return!D(e,t)}))}function mo(t){return"_value"in t?t._value:t.value}function yo(t){t.target.composing=!0}function _o(t){t.target.composing&&(t.target.composing=!1,go(t.target,"input"))}function go(t,e){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0),t.dispatchEvent(n)}function bo(t){return!t.componentInstance||t.data&&t.data.transition?t:bo(t.componentInstance._vnode)}var Co={model:fo,show:{bind:function(t,e,n){var r=e.value,o=(n=bo(n)).data&&n.data.transition,i=t.__vOriginalDisplay="none"===t.style.display?"":t.style.display;r&&o?(n.data.show=!0,io(n,(function(){t.style.display=i}))):t.style.display=r?i:"none"},update:function(t,e,n){var r=e.value;!r!=!e.oldValue&&((n=bo(n)).data&&n.data.transition?(n.data.show=!0,r?io(n,(function(){t.style.display=t.__vOriginalDisplay})):ao(n,(function(){t.style.display="none"}))):t.style.display=r?t.__vOriginalDisplay:"none")},unbind:function(t,e,n,r,o){o||(t.style.display=t.__vOriginalDisplay)}}},wo={name:String,appear:Boolean,css:Boolean,mode:String,type:String,enterClass:String,leaveClass:String,enterToClass:String,leaveToClass:String,enterActiveClass:String,leaveActiveClass:String,appearClass:String,appearActiveClass:String,appearToClass:String,duration:[Number,String,Object]};function $o(t){var e=t&&t.componentOptions;return e&&e.Ctor.options.abstract?$o(qe(e.children)):t}function xo(t){var e={},n=t.$options;for(var r in n.propsData)e[r]=t[r];var o=n._parentListeners;for(var i in o)e[w(i)]=o[i];return e}function Ao(t,e){if(/\d-keep-alive$/.test(e.tag))return t("keep-alive",{props:e.componentOptions.propsData})}var Oo=function(t){return t.tag||We(t)},ko=function(t){return"show"===t.name},So={name:"transition",props:wo,abstract:!0,render:function(t){var e=this,n=this.$slots.default;if(n&&(n=n.filter(Oo)).length){var r=this.mode,o=n[0];if(function(t){for(;t=t.parent;)if(t.data.transition)return!0}(this.$vnode))return o;var i=$o(o);if(!i)return o;if(this._leaving)return Ao(t,o);var a="__transition-"+this._uid+"-";i.key=null==i.key?i.isComment?a+"comment":a+i.tag:s(i.key)?0===String(i.key).indexOf(a)?i.key:a+i.key:i.key;var c=(i.data||(i.data={})).transition=xo(this),u=this._vnode,l=$o(u);if(i.data.directives&&i.data.directives.some(ko)&&(i.data.show=!0),l&&l.data&&!function(t,e){return e.key===t.key&&e.tag===t.tag}(i,l)&&!We(l)&&(!l.componentInstance||!l.componentInstance._vnode.isComment)){var f=l.data.transition=S({},c);if("out-in"===r)return this._leaving=!0,se(f,"afterLeave",(function(){e._leaving=!1,e.$forceUpdate()})),Ao(t,o);if("in-out"===r){if(We(i))return u;var d,p=function(){d()};se(c,"afterEnter",p),se(c,"enterCancelled",p),se(f,"delayLeave",(function(t){d=t}))}}return o}}},jo=S({tag:String,moveClass:String},wo);function Eo(t){t.elm._moveCb&&t.elm._moveCb(),t.elm._enterCb&&t.elm._enterCb()}function To(t){t.data.newPos=t.elm.getBoundingClientRect()}function Io(t){var e=t.data.pos,n=t.data.newPos,r=e.left-n.left,o=e.top-n.top;if(r||o){t.data.moved=!0;var i=t.elm.style;i.transform=i.WebkitTransform="translate("+r+"px,"+o+"px)",i.transitionDuration="0s"}}delete jo.mode;var Do={Transition:So,TransitionGroup:{props:jo,beforeMount:function(){var t=this,e=this._update;this._update=function(n,r){var o=Qe(t);t.__patch__(t._vnode,t.kept,!1,!0),t._vnode=t.kept,o(),e.call(t,n,r)}},render:function(t){for(var e=this.tag||this.$vnode.data.tag||"span",n=Object.create(null),r=this.prevChildren=this.children,o=this.$slots.default||[],i=this.children=[],a=xo(this),s=0;s-1?Kn[t]=e.constructor===window.HTMLUnknownElement||e.constructor===window.HTMLElement:Kn[t]=/HTMLUnknownElement/.test(e.toString())},S(An.options.directives,Co),S(An.options.components,Do),An.prototype.__patch__=z?lo:E,An.prototype.$mount=function(t,e){return function(t,e,n){var r;return t.$el=e,t.$options.render||(t.$options.render=ht),nn(t,"beforeMount"),r=function(){t._update(t._render(),n)},new hn(t,r,E,{before:function(){t._isMounted&&!t._isDestroyed&&nn(t,"beforeUpdate")}},!0),n=!1,null==t.$vnode&&(t._isMounted=!0,nn(t,"mounted")),t}(this,t=t&&z?function(t){return"string"==typeof t?document.querySelector(t)||document.createElement("div"):t}(t):void 0,e)},z&&setTimeout((function(){R.devtools&&rt&&rt.emit("init",An)}),0);const No=An;var Po=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("section",{attrs:{id:"app"}},[t._ssrNode("

我是App哈哈哈

"),n("Foo"),t._ssrNode(" "),n("Bar")],2)};Po._withStripped=!0;var Mo=function(){var t=this,e=t.$createElement;return(t._self._c||e)("section",{staticClass:"bar"},[t._ssrNode("

Bar

")])};function Lo(t,e,n,r,o,i,a,s){var c,u="function"==typeof t?t.options:t;if(e&&(u.render=e,u.staticRenderFns=n,u._compiled=!0),r&&(u.functional=!0),i&&(u._scopeId="data-v-"+i),a?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),o&&o.call(this,t),t&&t._registeredComponents&&t._registeredComponents.add(a)},u._ssrRegister=c):o&&(c=s?function(){o.call(this,(u.functional?this.parent:this).$root.$options.shadowRoot)}:o),c)if(u.functional){u._injectStyles=c;var l=u.render;u.render=function(t,e){return c.call(e),l(t,e)}}else{var f=u.beforeCreate;u.beforeCreate=f?[].concat(f,c):[c]}return{exports:t,options:u}}Mo._withStripped=!0;var Fo=Lo({name:"bar",data:function(){return{}},components:{},watch:{},mounted:function(){},methods:{click:function(){alert("click")}}},Mo,[],!1,(function(t){var e=n(415);e.__inject__&&e.__inject__(t)}),"2aa73eda","5c87ab7e");Fo.options.__file="src/components/Bar.vue";const Ro=Fo.exports;var Uo=function(){var t=this,e=t.$createElement;return(t._self._c||e)("section",{staticClass:"foo"},[t._ssrNode("

Fooqqq

")])};Uo._withStripped=!0;var Bo=Lo({name:"Foo",data:function(){return{}},components:{},watch:{},mounted:function(){},methods:{}},Uo,[],!1,(function(t){var e=n(107);e.__inject__&&e.__inject__(t)}),"54024074","47da2ab1");Bo.options.__file="src/components/Foo.vue";var Vo=Lo({name:"app",data:function(){return{}},components:{Foo:Bo.exports,Bar:Ro},watch:{},mounted:function(){},methods:{}},Po,[],!1,null,null,"64137b2d");Vo.options.__file="src/App.vue";const Ho=Vo.exports,zo=function(){return new No({render:function(t){return t(Ho)}})}},152:(t,e,n)=>{var r=n(645)((function(t){return t[1]}));r.push([t.id,"\nh1[data-v-2aa73eda] {\n color: yellow;\n}\n",""]),t.exports=r},652:(t,e,n)=>{var r=n(645)((function(t){return t[1]}));r.push([t.id,"\n.foo[data-v-54024074] {\n color: red;\n}\nh1[data-v-54024074] {\n color: red;\n}\n",""]),t.exports=r},645:t=>{"use strict";t.exports=function(t){var e=[];return e.toString=function(){return this.map((function(e){var n=t(e);return e[2]?"@media ".concat(e[2]," {").concat(n,"}"):n})).join("")},e.i=function(t,n,r){"string"==typeof t&&(t=[[null,t,""]]);var o={};if(r)for(var i=0;i{"use strict";n.r(e),n.d(e,{default:()=>a});var r=n(564),o=n.n(r),i={};for(const t in r)"default"!==t&&(i[t]=()=>r[t]);n.d(e,i);const a=o()},107:(t,e,n)=>{"use strict";n.r(e),n.d(e,{default:()=>a});var r=n(441),o=n.n(r),i={};for(const t in r)"default"!==t&&(i[t]=()=>r[t]);n.d(e,i);const a=o()},564:(t,e,n)=>{var r=n(152);"string"==typeof r&&(r=[[t.id,r,""]]),r.locals&&(t.exports=r.locals);var o=n(703).Z;t.exports.__inject__=function(t){o("18786287",r,!1,t)}},441:(t,e,n)=>{var r=n(652);"string"==typeof r&&(r=[[t.id,r,""]]),r.locals&&(t.exports=r.locals);var o=n(703).Z;t.exports.__inject__=function(t){o("506256e7",r,!1,t)}},703:(t,e,n)=>{"use strict";function r(t,e,n,r){if(r||"undefined"==typeof __VUE_SSR_CONTEXT__||(r=__VUE_SSR_CONTEXT__),r){r.hasOwnProperty("styles")||(Object.defineProperty(r,"styles",{enumerable:!0,get:function(){return o(r._styles)}}),r._renderStyles=o);var i=r._styles||(r._styles={});e=function(t,e){for(var n=[],r={},o=0;o"+r.css+""}return e}n.d(e,{Z:()=>r})}},e={};function n(r){if(e[r])return e[r].exports;var o=e[r]={id:r,exports:{}};return t[r](o,o.exports,n),o.exports}return n.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return n.d(e,{a:e}),e},n.d=(t,e)=>{for(var r in e)n.o(e,r)&&!n.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},n.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),n.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n(241)})(); --------------------------------------------------------------------------------