详解如何将 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 相关文章推荐
javascript笔试题目附答案@20081025_jb51.net
Oct 26 Javascript
js获取当前select 元素值的代码
Apr 19 Javascript
jQuery1.9.1针对checkbox的调整方法(prop)
May 01 Javascript
JavaScript中三种异步上传文件方式
Mar 06 Javascript
js实现定时进度条完成后切换图片
Jan 04 Javascript
Node.js应用设置安全的沙箱环境
Apr 23 Javascript
快速解决select2在bootstrap模态框中下拉框隐藏的问题
Aug 10 Javascript
JavaScript实现表单注册、表单验证、运算符功能
Oct 15 Javascript
React+Antd+Redux实现待办事件的方法
Mar 14 Javascript
Node 搭建一个静态资源服务器的实现
May 20 Javascript
javascript实现鼠标点击生成文字特效
Dec 24 Javascript
vue 基于abstract 路由模式 实现页面内嵌的示例代码
Dec 14 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
介绍php设计模式中的工厂模式
2008/06/12 PHP
pdo中使用参数化查询sql
2011/08/11 PHP
PHP中使用foreach和引用导致程序BUG的问题介绍
2012/09/05 PHP
php实现微信扫码自动登陆与注册功能
2016/09/22 PHP
php实现微信公众号创建自定义菜单功能的实例代码
2019/06/11 PHP
避免 showModalDialog 弹出新窗体的原因分析
2010/05/31 Javascript
Javascript实现带关闭按钮的网页漂浮广告代码
2014/01/12 Javascript
javascript的switch用法注意事项分析
2015/02/02 Javascript
javascript 实现map集合
2015/04/03 Javascript
javascript文本模板用法实例
2015/07/31 Javascript
js判断上传文件后缀名是否合法
2016/01/28 Javascript
Bootstrap每天必学之按钮(Button)插件
2016/04/25 Javascript
js的form表单提交url传参数(包含+等特殊字符)的两种解决方法
2016/05/25 Javascript
BootStrap创建响应式导航条实例代码
2016/05/31 Javascript
微信小程序开发之圆形菜单 仿建行圆形菜单实例
2016/12/12 Javascript
nodejs用gulp管理前端文件方法
2018/06/24 NodeJs
JavaScript深入V8引擎以及编写优化代码的5个技巧
2019/06/24 Javascript
vue实现中部导航栏布局功能
2019/07/30 Javascript
微信小程序swiper实现文字纵向轮播提示效果
2020/01/21 Javascript
[01:21]DOTA2新纪元-7.0新版本即将开启!
2016/12/11 DOTA
[01:36]DOTA2完美大师赛趣味视频之与队友相处的十万个技巧
2017/11/19 DOTA
Python 中 Meta Classes详解
2016/02/13 Python
说一说Python logging
2016/04/15 Python
浅谈python中的面向对象和类的基本语法
2016/06/13 Python
pyqt5与matplotlib的完美结合实例
2019/06/21 Python
使用Python快乐学数学Github万星神器Manim简介
2019/08/07 Python
在django-xadmin中APScheduler的启动初始化实例
2019/11/15 Python
优秀员工自荐信范文
2013/10/05 职场文书
事业单位绩效考核实施方案
2014/03/27 职场文书
公务员试用期满考核材料
2014/05/22 职场文书
婚内房产协议书范本
2014/10/02 职场文书
党员承诺书格式范文
2015/04/28 职场文书
计划生育责任书
2015/05/09 职场文书
副校长2015年教育教学工作总结
2015/07/27 职场文书
我的收音机情缘
2022/04/05 无线电
Python获取字典中某个key的value
2022/04/13 Python