从0到1构建vueSSR项目之node以及vue-cli3的配置
程序员文章站
2022-08-02 12:58:02
前言
上一次做了,原本计划今天要做vuex部分,但是想了想,发现vuex单独的客户端部分穿插解释起来很麻烦,所以今天改做服务端部分。
服务端部分做完,再去做vu...
前言
上一次做了,原本计划今天要做vuex部分,但是想了想,发现vuex单独的客户端部分穿插解释起来很麻烦,所以今天改做服务端部分。
服务端部分做完,再去做vuex的部分,这样就会很清晰。
vue ssr是分两个端,一个是客户端,一个是服务端。
所以要做两个cli3的配置。
那么下面就直接开始做吧。
修改package.json的命令
//package.json :client代表客户端 :server代表服务端 //使用vue_node来作为运行环境是node的标识 //cli3内置 命令 --no-clean 不会清除dist文件 "scripts": { "serve:client": " vue-cli-service serve", "build":"npm run build:server -- --silent && npm run build:client -- --no-clean --silent", "build:client": "vue-cli-service build", "build:server": "cross-env vue_node=node vue-cli-service build", "start:server": "cross-env node_env=production nodemon nodescript/index" }
修改vue.config.js配置
添加完相关脚本命令之后,我们开始改造cli3配置。
首先要require('vue-server-renderer')
然后再根据vue_node环境变量来决定编译的走向以及生成不同的环境清单
先做cli3服务端的入口文件
// src/entry/server.js import { createapp } from '../main.js' export default context => { return new promise((resolve, reject) => { const { app, router } = createapp(context.data) //根据node传过来的路由 来调用router路由的指向 router.push(context.url) router.onready(() => { //获取当前路由匹配的组件数组。 const matchedcomponents = router.getmatchedcomponents() //长度为0就是没找到该路由所匹配的组件 //可以路由设置重定向或者传回node node来操作也可以 if (!matchedcomponents.length) { return reject({ code: 404 }) } resolve(app) }, reject) }) }
这里是cli3的配置
//vue.config.js const serverplugin = require('vue-server-renderer/server-plugin'),//生成服务端清单 clientplugin = require('vue-server-renderer/client-plugin'),//生成客户端清单 nodeexternals = require('webpack-node-externals'),//忽略node_modules文件夹中的所有模块 vue_node = process.env.vue_node === 'node', entry = vue_node ? 'server' : 'client';//根据环境变量来指向入口 module.exports = { css: { extract: false//关闭提取css,不关闭 node渲染会报错 }, configurewebpack: () => ({ entry: `./src/entry/${entry}`, output: { filename: 'js/[name].js', chunkfilename: 'js/[name].js', librarytarget: vue_node ? 'commonjs2' : undefined }, target: vue_node ? 'node' : 'web', externals: vue_node ? nodeexternals({ //设置白名单 whitelist: /\.css$/ }) : undefined, plugins: [//根据环境来生成不同的清单。 vue_node ? new serverplugin() : new clientplugin() ] }), chainwebpack: config => { config.resolve .alias .set('vue$', 'vue/dist/vue.esm.js') config.module .rule('vue') .use('vue-loader') .tap(options => { options.optimizessr = false; return options; }); config.module .rule('images') .use('url-loader') .tap(options => { options = { limit: 1024, fallback:'file-loader?name=img/[path][name].[ext]' } return options; }); } }
node相关配置
用于node渲染 必然要拦截get请求的。然后根据get请求地址来进行要渲染的页面。
官方提供了
大概的方式就是 node拦截所有的get请求,然后将获取到的路由地址,传给前台,然后使用router实例进行push
再往下面看之前 先看一下官方文档
创建bundlerenderer
createbundlerenderer
将 vue 实例渲染为字符串。
rendertostring
渲染应用程序的模板
生成所需要的客户端或服务端清单
clientmanifest
先创建 服务端所需要的模板
//public/index.nodetempalte.html <!doctype html> <html> <head> <meta http-equiv="x-ua-compatible" content="ie=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <link rel="icon" href="/favicon.ico" rel="external nofollow" > <meta charset="utf-8"> <title>vuessr</title> </head> <body> <!--vue-ssr-outlet--> </body> </html>
node部分
先创建三个文件
index.js //入口
proxy.js //代理
server.js //主要配置
//server.js const fs = require('fs'); const { resolve } = require('path'); const express = require('express'); const app = express(); const proxy = require('./proxy'); const { createbundlerenderer } = require('vue-server-renderer') //模板地址 const templatepath = resolve(__dirname, '../public/index.nodetempalte.html') //客户端渲染清单 const clientmanifest = require('../dist/vue-ssr-client-manifest.json') //服务端渲染清单 const bundle = require('../dist/vue-ssr-server-bundle.json') //读取模板 const template = fs.readfilesync(templatepath, 'utf-8') const renderer = createbundlerenderer(bundle,{ template, clientmanifest, runinnewcontext: false }) //代理相关 proxy(app); //请求静态资源相关配置 app.use('/js', express.static(resolve(__dirname, '../dist/js'))) app.use('/css', express.static(resolve(__dirname, '../dist/css'))) app.use('/font', express.static(resolve(__dirname, '../dist/font'))) app.use('/img', express.static(resolve(__dirname, '../dist/img'))) app.use('*.ico', express.static(resolve(__dirname, '../dist'))) //路由请求 app.get('*', (req, res) => { res.setheader("content-type", "text/html") //传入路由 src/entry/server.js会接收到 使用vuerouter实例进行push const context = { url: req.url } renderer.rendertostring(context, (err, html) => { if (err) { if (err.url) { res.redirect(err.url) } else { res.status(500).end('500 | 服务器错误'); console.error(`${req.url}: 渲染错误 `); console.error(err.stack) } } res.status(context.httpstatus || 200) res.send(html) }) }) module.exports = app; //proxy.js const proxy = require('http-proxy-middleware'); function proxyconfig(obj){ return { target:'localhost:8081', changeorigin:true, ...obj } } module.exports = (app) => { //代理开发环境 if (process.env.node_env !== 'production') { app.use('/js/main*', proxy(proxyconfig())); app.use('/*hot-update*',proxy(proxyconfig())); app.use('/sockjs-node',proxy(proxyconfig({ws:true}))); } } //index.js const app = require('./server') app.listen(8080, () => { console.log('\033[42;37m done \033[40;33m localhost:8080 服务已启动\033[0m') })
做完这一步之后,就可以预览基本的服务渲染了。
后面就只差开发环境的配置,以及到node数据的传递(vuex)
npm run build npm run start:server 打开localhost:8080 f12 - network - doc 就可以看到内容
最终目录结构
|-- vuessr |-- .gitignore |-- babel.config.js |-- package-lock.json |-- package.json |-- readme.md |-- vue.config.js |-- nodescript //node 渲染配置 | |-- index.js | |-- proxy.js | |-- server.js |-- public//模板文件 | |-- favicon.ico | |-- index.html | |-- index.nodetempalte.html |-- src |-- app.vue |-- main.js |-- router.config.js//路由集合 |-- store.config.js//vuex 集合 |-- assets//全局静态资源源码 | |-- 备注.txt | |-- img | |-- logo.png |-- components//全局组件 | |-- head | |-- index.js | |-- index.scss | |-- index.vue | |-- img | |-- logo.png |-- entry//cli3入口 | |-- client.js | |-- server.js | |-- 备注.txt |-- methods//公共方法 | |-- 备注.txt | |-- mixin | |-- index.js |-- pages//源码目录 | |-- home | | |-- index.js | | |-- index.scss | | |-- index.vue | | |-- img | | | |-- flow.png | | | |-- head_portrait.jpg | | | |-- logo.png | | | |-- vuessr.png | | |-- vue | | | |-- index.js | | | |-- index.scss | | | |-- index.vue | | |-- vuecli3 | | | |-- index.js | | | |-- index.scss | | | |-- index.vue | | |-- vuessr | | | |-- index.js | | | |-- index.scss | | | |-- index.vue | | |-- vuex | | |-- index.js | | |-- index.scss | | |-- index.vue | |-- router//路由配置 | | |-- index.js | |-- store//vuex配置 | |-- all.js | |-- gather.js | |-- index.js |-- static//cdn资源 |-- 备注.txt
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。