详解如何将 Vue-cli 改造成支持多页面的 history 模式


Posted in Javascript onNovember 20, 2017

标题可能描述不准确, 大概就是这么个需求:

用 Vue-cli 搭建一个多入口, 多页面的站点, 也就是通过html-webpack-plugin插件会生成多个 .html 文件, 在默认下, 是只有 index.html 这个入口可以用 history 模式, 如: http://www.xxx.com/xxx/xxx, 而其他的入口只能用 hash 模式, 如: http://www.xxx.com/admin.html#/xxx/xxx, 因为webpack-dev-middleware会将所有的路由都指向 index.html 文件, 假如线上的时候, 都需要 history 模式, 这样多少会造成麻烦.

真是太二了, 刚写完文章就发现connect-history-api-fallback这个插件就是做这个的...

方法更新如下:

修改 build/dev-server.js 文件

app.use(require('connect-history-api-fallback')())

改成

var history = require('connect-history-api-fallback')
app.use(history({
  rewrites: [
    { from: 'index', to: '/index.html'}, // 默认入口
    { from: /\/backend/, to: '/backend.html'}, // 其他入口
    { from: /^\/backend\/.*$/, to: '/backend.html'},
  ]
}))

具体规则就参考: https://github.com/bripkens/connect-history-api-fallback

-------------- 以下代码请无视 --------------

下面我们就来改造下, 让所有入口都支持 history 模式:

1. 首先, 我们在 build 目录下建立个 setup-dev-server.js 文件, 里面代码如下:

const path = require('path')
const webpack = require('webpack')
const clientConfig = require('./webpack.dev.conf') // 引入开发环境下的 webpack 配置文件

module.exports = function setupDevServer(app, opts) {
  const clientCompiler = webpack(clientConfig)
  // 加载 webpack-dev-middleware 插件
  const devMiddleware = require('webpack-dev-middleware')(clientCompiler, {
    publicPath: clientConfig.output.publicPath,
    stats: {
      colors: true,
      chunks: false
    }
  })
  app.use(devMiddleware)
  // 关键代码开始
  // 因为开发环境下, 所有的文件都在内存里, 包括由 html-webpack-plugin 生成的 .html 文件, 所以我们需要用 webpack-dev-middleware 提供的 api 从内存里读取
  clientCompiler.plugin('done', () => {
    const fs = devMiddleware.fileSystem // 访问内存
    const filePath = path.join(clientConfig.output.path, 'index.html') // 读取的文件, 文件名和 html-webpack-plugin 生成的文件名要求一致
    if (fs.existsSync(filePath)) { // 判断下文件是否存在
      const index = fs.readFileSync(filePath, 'utf-8') // 从内存里取出
      opts.indexUpdated(index) // 将取出的文件通过 indexUpdated 函数返回, 这个函数怎么来的, 后面会说明
    }
    const adminPath = path.join(clientConfig.output.path, 'backend.html') // 同上, 这是第二个入口生成的 .html 文件, 如果还有其他入口, 这个多复制几份
    if (fs.existsSync(adminPath)) {
      const admin = fs.readFileSync(adminPath, 'utf-8')
      opts.adminUpdated(admin)
    }
  })

  // 加载热重载模块
  app.use(require('webpack-hot-middleware')(clientCompiler))
  var hotMiddleware = require('webpack-hot-middleware')(clientCompiler)
  // 当修改 html-webpack-plugin 模版时, 自动刷新整个页面
  clientCompiler.plugin('compilation', function(compilation) {
    compilation.plugin('html-webpack-plugin-after-emit', function(data, cb) {
      hotMiddleware.publish({
        action: 'reload'
      })
      cb()
    })
  })
}

2. 修改 build/dev-server.js 文件

主要修改文件中var app = express()到module.exports = app.listen(port, function (err) {之间的代码

var app = express()

var indexHTML
var adminHTML

// 引用前面创建的文件, 并将两个保存内容的函数传过去, 这里保存内容的变量写成对象或者数组也可以, 还可以少点代码
require('../config/setup-dev-server')(app, {
  indexUpdated: index => {
    indexHTML = index
  },
  adminUpdated: index => {
    adminHTML = index
  },
})

// 加载反向代理
Object.keys(proxyTable).forEach(function(context) {
  var options = proxyTable[context]
  if (typeof options === 'string') {
    options = {
      target: options
    }
  }
  app.use(proxyMiddleware(context, options))
})
// 设置静态文件夹路由
var staticPath = path.posix.join(config.assetsPublicPath, config.assetsSubDirectory)
app.use(staticPath, express.static('./static'))

// 入口1路由
app.get(['/', '/category/:id'], (req, res) => {
  res.send(indexHTML)
})

// 入口2路由
app.get(['/backend', '/backend/*'], (req, res) => {
  res.send(adminHTML)
})

// 404 页面
app.get('*', (req, res) => {
  res.send('HTTP STATUS: 404')
})

app.use(function(req, res, next) {
  var err = new Error('Not Found')
  err.status = 404
  next(err)
})

app.use(function(err, req, res) {
  res.status(err.status || 500)
  res.send(err.message)
})

module.exports = app.listen(port, function(err) {

3. npm run dev 开始愉快的写代码吧

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JQuery困惑—包装集 DOM节点
Oct 16 Javascript
js DOM的学习笔记
Dec 22 Javascript
js修改input的type属性及浏览器兼容问题探讨与解决
Jan 23 Javascript
在javascript中对于DOM的加强
Apr 11 Javascript
浅析Node在构建超媒体API中的作用
Jul 30 Javascript
JS显示下拉列表框内全部元素的方法
Mar 31 Javascript
简单实现jQuery进度条轮播实例代码
Jun 20 Javascript
js从外部获取图片的实现方法
Aug 05 Javascript
利用CSS、JavaScript及Ajax实现图片预加载的三大方法
Jan 22 Javascript
Vue之Watcher源码解析(2)
Jul 19 Javascript
vue2中的keep-alive使用总结及注意事项
Dec 21 Javascript
vue-cli3.x配置全局的scss的时候报错问题及解决
Apr 30 Vue.js
详解Vue2 SSR 缓存 Api 数据
Nov 20 #Javascript
Three.js开发实现3D地图的实践过程总结
Nov 20 #Javascript
jquery ztree实现右键收藏功能
Nov 20 #jQuery
深入理解vuex2.0 之 modules
Nov 20 #Javascript
three.js中文文档学习之如何本地运行详解
Nov 20 #Javascript
AngularJS实现自定义指令及指令配置项的方法
Nov 20 #Javascript
详解webpack + react + react-router 如何实现懒加载
Nov 20 #Javascript
You might like
异世界新番又来了,同样是从零开始,男主的年龄降到5岁
2020/04/09 日漫
php站内搜索并高亮显示关键字的实现代码
2011/12/29 PHP
PHP运行SVN命令显示某用户的文件更新记录的代码
2014/01/03 PHP
PHP strcmp()和strcasecmp()的区别实例
2016/11/05 PHP
JavaScript Accessor实现说明
2010/12/06 Javascript
javascript右下角弹层及自动隐藏(自己编写)
2013/11/20 Javascript
firefox浏览器用jquery.uploadify插件上传时报HTTP 302错误
2015/03/01 Javascript
JS文字球状放大效果代码分享
2015/08/19 Javascript
详解JavaScript逻辑And运算符
2015/12/04 Javascript
详谈jQuery.load()和Jsp的include的区别
2017/04/12 jQuery
vue动画打包后失效问题的解决方法
2018/09/18 Javascript
jQuery实现的模仿雨滴下落动画效果
2018/12/11 jQuery
小程序组件之自定义顶部导航实例
2019/06/12 Javascript
jQuery实现异步上传一个或多个文件
2020/08/17 jQuery
[08:47]DOTA2每周TOP10 精彩击杀集锦vol.6
2014/06/25 DOTA
[14:56]教你分分钟做大人:巫医
2014/10/30 DOTA
[52:08]DOTA2上海特级锦标赛主赛事日 - 3 败者组第三轮#2Fnatic VS OG第一局
2016/03/05 DOTA
[01:34]传奇从这开始 2016国际邀请赛中国区预选赛震撼开启
2016/06/26 DOTA
将图片文件嵌入到wxpython代码中的实现方法
2014/08/11 Python
分享一个常用的Python模拟登陆类
2015/03/29 Python
详解Python中的多线程编程
2015/04/09 Python
python实现网站的模拟登录
2016/01/04 Python
Python爬虫模拟登录带验证码网站
2016/01/22 Python
python3模拟实现xshell远程执行liunx命令的方法
2019/07/12 Python
Python基于Socket实现简易多人聊天室的示例代码
2020/11/29 Python
如何用border-image实现文字气泡边框的示例代码
2020/01/21 HTML / CSS
英国排名第一的LED灯泡网站:LED Bulbs
2019/09/03 全球购物
VLAN和VPN有什么区别?分别实现在OSI的第几层?
2014/12/23 面试题
企业门卫岗位职责
2013/12/12 职场文书
运动会通讯稿200字
2014/02/16 职场文书
社会治安综合治理管理责任书
2014/04/16 职场文书
2015年教育实习工作总结
2015/04/24 职场文书
2015年工程部工作总结
2015/04/30 职场文书
素质拓展训练感想
2015/08/07 职场文书
《颐和园》教学反思
2016/02/19 职场文书
Python调用腾讯API实现人脸身份证比对功能
2022/04/04 Python