Skip to content

Commit

Permalink
Feat: 开发环境history路由支持
Browse files Browse the repository at this point in the history
  • Loading branch information
毛瑞 authored and Maorey committed May 19, 2020
1 parent 64ab1c2 commit bb8b5df
Show file tree
Hide file tree
Showing 15 changed files with 143 additions and 124 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# 更新日志

## v 1.2.18

- 完善多SPA history 路由支持

## v 1.2.17

- 完善多SPA支持
Expand Down
17 changes: 10 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ yarn vue-cli-service help # [命令] : 比如 yarn vue-cli-service help test:e2e
- 尽量**不要使用全局注册**(插件/组件/指令/混入等)以优化性能并且代码更清晰、更易维护
- 尽量**按照依赖库的文档描述**来使用她, 从其源码(src)引入模块(css/scss/.../js/mjs/ts/jsx/tsx/vue), 将可能**不会被处理**且更可能随版本更新改变, 需要时可以从其构建后的 lib/dist 等目录引入或者增加一些配置(需要了解模块解析及转码规则和相关插件, 不推荐)
- 若开发环境出现缓存相关错误信息导致热更新慢, 可以删除 `node_modules/.cache` 文件夹再试
- 路由路径不应出现符号 `.` , 以方便 `history 路由` 模式开发/部署

### 风格建议

Expand Down Expand Up @@ -656,8 +657,8 @@ yarn vue-cli-service help # [命令] : 比如 yarn vue-cli-service help test:e2e
```
- 所有视图组件可接收props:`route`代替`this.$route`, 区别是: **只在首次进入当前视图或当前视图url发生变化时改变**
- 路由视图不需要被缓存的, 可以在meta申明/`deactivated`钩子销毁实例(`this.$destroy()`)或`activated`钩子进行更新
- 为避免渲染错误, 请务必为<b style="color: red;">循环创建的组件</b>**加上 `key`**, 特别是 `tsx/ts/jsx/js`
- **路由视图**不需要被缓存的, 可以在`meta`申明/`deactivated`钩子销毁实例(`this.$destroy()`)或`activated`钩子进行更新
- 为避免渲染错误, 请务必为 <b style="color: red;">循环创建的组件</b> **加上 `key`**, 需要特别注意 `tsx/ts/jsx/js` 文件(没有代码提示)
### 配置和优化
Expand Down Expand Up @@ -699,19 +700,21 @@ yarn vue-cli-service help # [命令] : 比如 yarn vue-cli-service help test:e2e
- 开启 `gzip` 压缩, 并重用已有 `gz` 文件 `gzip_static on;`
- 缓存静态资源(html 可减少缓存时间)
- [HTTP2 Server Push](https://www.nginx.com/blog/nginx-1-13-9-http2-server-push) 服务器推送, 需要 `nginx` 版本**1.13.9**及以上, [文档链接](http://nginx.org/en/docs/http/ngx_http_v2_module.html#http2_push_preload)
- 多个SPA history路由部署, 只能一个SPA一个location了么(待运维大佬解决)?
- 多个SPA(即 `html` 文件)以**history路由**(访问url不以`#`号标识)部署:
- 一个 `html` 一个 location 或 待运维大佬完善(示例如下)
- 按照注释修改**每个** `html` 的配置, 其中 `base` 改为对应访问路径
配置示例( `nginx.conf` 文件, `xxx` 换成对应值):
```bash
http {
include /etc/nginx/mime.types;
include xxx/mime.types;
default_type application/octet-stream;

# log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
# access_log /var/log/nginx/access.log main;
# access_log xxx/access.log main;

sendfile on;
# tcp_nopush on;
Expand Down Expand Up @@ -771,7 +774,7 @@ http {
# error_page 404 /404.html; # 未知页

location / {
# rewrite ^/(?:path|path-alias)/(.*)$ /$1 last; # 兼容某些路由
# rewrite ^/(?:path|path-alias)/(.*)$ /$1 last; # 兼容某些url
# 设置静态资源缓存(文件名已带内容哈希了)
if ($uri ~ .*\.(?:js|css|jpg|jpeg|gif|png|ico|gz|svg|svgz|ttf|eot|mp4)$) {
expires 7d; # d: 天
Expand All @@ -787,7 +790,7 @@ http {

set $u /; # for 多页history路由 其他location: ^/location([^/]+)
if ($uri ~ ^/([^/]+)) {
set $u $1.html; # 待测试
set $u $1.html; # 待测试并完善
}
try_files $uri $uri/ $uri.html $u / =404;
# try_files $uri $uri/ $uri.html /location$u /location =404;
Expand Down
48 changes: 30 additions & 18 deletions build/devServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = function(ENV, PAGES) {
const TARGET = 'PROXY_TARGET'
const FIELD = ENV.PROXY_FIELD
const REG_BASE = /^BASE_PATH(\d*)$/
const REG_URL = /^((?:http|ws)s?:\/\/)[^:/]+(.*)/
const REG_URL = /^((?:http|ws)s?:\/\/)[^:/]+(.*)$/

const removeField = (url, field) =>
url.replace(
Expand Down Expand Up @@ -73,8 +73,11 @@ module.exports = function(ENV, PAGES) {
}

// http2 应该是不能配置了
const REG_SLASHES = /\/+/g
const REG_FILES = /\..+$/
const REG_SPA = /^\/([^/]+)(.*)$/
const REG_HTML = /\.html$/
const REG_FILES = /[^/]+\.[^/]+$/
const REG_PATH = /^(?:http|ws)s?:\/\/[^/]+(.*)$/
const REG_SLASHES = /\/+/
return {
host,
port,
Expand All @@ -84,26 +87,35 @@ module.exports = function(ENV, PAGES) {
overlay: { errors: true }, // lint
openPage: ENV.DEV_SERVER_PAGE || '',
historyApiFallback: {
// index: '/index.html',
rewrites: [
{
// SPA可省略.html 支持history路由(路径不能有'.', 因为用REG_FILES匹配文件)
// TODO: 精确匹配已有资源
from: /./,
to({ parsedUrl: { pathname, search } }) {
search || (search = '')
const paths = pathname.replace(ENV.BASE_URL, '').split('/')
paths[0] || paths.shift()
const entry = paths.shift()
to(context) {
const parsedUrl = context.parsedUrl
const search = parsedUrl.search || ''
let pathname = REG_SPA.exec(parsedUrl.pathname)

return (
(PAGES.includes(entry)
? `${ENV.BASE_URL}/${
paths.length && REG_FILES.test(pathname)
? paths.join('/')
: `${entry}.html`
}`.replace(REG_SLASHES, '/')
: pathname) + search
)
const entry = pathname[1].replace(REG_HTML, '')
if (PAGES[entry]) {
pathname = pathname[2]
if (REG_FILES.test(pathname)) {
let referer = context.request.headers.referer
if (referer) {
pathname = parsedUrl.pathname.split(REG_SLASHES)
referer = referer.replace(REG_PATH, '$1').split(REG_SLASHES)
while (pathname[0] === referer[0]) {
pathname.shift()
referer.shift()
}
return '/' + pathname.join('/') + search
}
return pathname + search
}
return `/${entry}.html${search}`
}
return parsedUrl.pathname + search
},
},
],
Expand Down
6 changes: 3 additions & 3 deletions build/development.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
* @param {chainWebpack} config 配置对象
* https://github.com/neutrinojs/webpack-chain#getting-started
*/
module.exports = function(config) {
module.exports = function(config, ENV) {
// https://webpack.js.org/configuration/devtool/#devtool
config.devtool(process.env.DEV_TOOL || 'eval')
config.devtool(ENV.DEV_TOOL || 'eval')
/// 避免同名.vue文件sourceMap冲突 ///
// https://webpack.js.org/configuration/output/#outputdevtoolmodulefilenametemplate
// config.output.devtoolFallbackModuleFilenameTemplate(
Expand All @@ -35,7 +35,7 @@ module.exports = function(config) {

// return `webpack://${info.namespace}/${fileName}`
// })
// config.output.ecmaVersion(+process.env.ES_VERSION || 6) // WIP
// config.output.ecmaVersion(+ENV.ES_VERSION || 6) // WIP

/// 文件监听 ///
config.watchOptions({ ignored: /node_modules/ })
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vue-tpl",
"version": "1.2.17",
"version": "1.2.18",
"private": false,
"description": "vue + vuex + vue router + TypeScript(支持 JavaScript) 模板",
"author": "毛瑞 <[email protected]>",
Expand Down
24 changes: 8 additions & 16 deletions src/components/RouterViewTransparent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ import getKey from '@/utils/getKey'
// import(/* webpackChunkName: "ihOne" */ './ModuleOne')
// )

/** 透明分发路由(支持嵌套)
/** 透明分发路由(支持嵌套), props: { max: number }
* 可以给个key防止<RVT>复用:
* <KeepAlive>
* <RouterView :key="$route.meta.code" />
* <KeepAlive />
*/
export default {
name: 'RVT',
props: ['route'],
props: ['route', 'max'],
data() {
return { d: 0 } // 是否失活/离开
return { d: 0 } // d: 是否失活/离开
},
beforeRouteUpdate(this: any, to, from, next) {
this.d = 0
Expand All @@ -47,22 +47,14 @@ export default {
return this.n
}

let max = this.max
max > 1 || (max = CONFIG.subPage > 1 ? CONFIG.subPage : 1)
const meta = (this.route || this.$route).meta
meta.k || (meta.k = getKey('v'))
return (this.n = h(
'KeepAlive',
{
props: {
exclude: this.$router.$.e,
max: CONFIG.subPage > 1 ? CONFIG.subPage : 1,
},
},
[
h(
'RouterView',
{ key: meta.k || (meta.k = getKey('v')) },
this.$slots.default
),
]
{ props: { exclude: this.$router.$.e, max: max } },
[h('RouterView', { key: meta.k }, this.$slots.default)]
))
},
} as Component
60 changes: 22 additions & 38 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
export default {
/*! 【全局配置(时间单位ms)】 */

/* !【↓应用跳转配置↓】history路由必须绝对路径 */
/*! 索引页 */
/** 索引页 */
/*! 【↓ SPA配置 ↓】history路由必须绝对路径 */
/*! 首页 */
/** 首页 */
index: './',

/*! 登录页 */
Expand All @@ -26,16 +26,26 @@ export default {
/*! 错误页 */
/** 错误页 */
error: '50x',
/*! 【↑ SPA配置 ↑】 */

/* !【↑应用跳转配置↑】 */

/*! 接口地址(hash路由建议相对路径, 比如'api') */
/** 接口地址(hash路由建议相对路径, 比如'api') */
baseUrl: process.env.BASE_PATH,

/*! 网站路径, history路由必须/开头 */
/** 网站路径, history路由必须/开头 */
base: '',
/** 去指定SPA
* @param id SPA ID, 见this键值
*
* falsy: 去登录页
*
* string: 去指定页
*
* 不存在的id: 未知页
* @param query 查询参数 自己拼 ?foo=0&bar=1#hash...
*/
g(id?: string, search?: string) {
try {
window.stop() // 停止加载资源
} catch (error) {}
location.href =
(id ? (this as any)[id] || this.notFind : this.login) + (search || '')
throw 0 // eslint-disable-line no-throw-literal
},

/*! 接口请求超时 0表示不限制 */
/** 接口请求超时 0表示不限制 */
Expand All @@ -49,14 +59,6 @@ export default {
/** 全局接口响应缓存最大存活时间 */
apiCacheAlive: 3 * 1000,

/*! token cookie 字段 */
/** token cookie 字段 */
cookie: 'Authorization',

/*! token head 字段 */
/** token head 字段 */
head: 'Authorization',

/*! 身份有效期(取与服务端有效期的最小值) */
/** 身份有效期(取与服务端有效期的最小值) */
tokenAlive: 2 * 60 * 60 * 1000,
Expand All @@ -72,22 +74,4 @@ export default {
/*! 最大页面缓存时间 */
/** 最大页面缓存时间 */
pageAlive: 30 * 1000,

/** 去指定页
* @param id SPA ID, 见this键值
* falsy: 去登录页
* string: 去指定页
* 不存在的id: 未知页
*/
g(id?: string) {
if (id) {
location.href = (this as any)[id] || this.notFind
} else {
try {
window.stop() // 停止加载资源
} catch (error) {}
location.href = this.login
throw 0 // eslint-disable-line no-throw-literal
}
},
}
16 changes: 10 additions & 6 deletions src/pages/index/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
/*
* @Description: index页全局配置
* @Author: 毛瑞
* @Date: 2019-07-08 17:00:16
*/
/** SPA 配置 */
export default {
/*! 【index页配置】 */
/*! 【↓ history路由必须绝对路径 ↓】 */
/*! 网站路径 */
/** 网站路径 */
base: '',

/*! 接口地址 */
/** 接口地址 */
baseUrl: process.env.BASE_PATH,
/*! 【↑ history路由必须绝对路径 ↑】 */

/*! 图表重绘间隔(ms) */
/** 图表重绘间隔(ms)
Expand Down
3 changes: 3 additions & 0 deletions src/pages/index/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import router from './router'
import store from './store'
import App from './App'

import CONFIG from './config'
import mount from '@/functions/main'
import { setBase } from '@/utils/ajax'
import './registerServiceWorker'

setBase(CONFIG.baseUrl)
mount(App, router, store)
2 changes: 1 addition & 1 deletion src/pages/index/route/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
import { RouterOptions } from 'vue-router'

import CONFIG from '@/config'
import CONFIG from '../config'
import { home, about } from '@index/views'

export default {
Expand Down
12 changes: 12 additions & 0 deletions src/pages/other/config/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/** SPA 配置 */
export default {
/*! 【↓ history路由必须绝对路径 ↓】 */
/*! 网站路径 */
/** 网站路径 */
base: '',

/*! 接口地址 */
/** 接口地址 */
baseUrl: process.env.BASE_PATH,
/*! 【↑ history路由必须绝对路径 ↑】 */
}
3 changes: 3 additions & 0 deletions src/pages/other/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import router from './router'
import store from './store'
import App from './App'

import CONFIG from './config'
import mount from '@/functions/main'
import { setBase } from '@/utils/ajax'
import './registerServiceWorker'

setBase(CONFIG.baseUrl)
mount(App, router, store)
2 changes: 1 addition & 1 deletion src/pages/other/route/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*/
import { RouterOptions } from 'vue-router'

import CONFIG from '@/config'
import CONFIG from '../config'
import { home, about } from '@other/views'

export default {
Expand Down
Loading

0 comments on commit bb8b5df

Please sign in to comment.