详解如何将 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 语法集锦 脚本之家基础推荐
Nov 15 Javascript
Jquery Ajax的Get方式时需要注意URL地方
Apr 07 Javascript
捕获键盘事件(且兼容各浏览器)
Jul 03 Javascript
ajax与302响应代码测试
Oct 23 Javascript
js 将json字符串转换为json对象的方法解析
Nov 13 Javascript
javascript判断变量是否有值的方法
Apr 20 Javascript
jQuery简单实现验证邮箱格式
Jul 15 Javascript
js实现简单秒表走动的时钟特效
Mar 25 Javascript
jQuery简单实现对数组去重及排序操作实例
Oct 31 jQuery
Vue SPA单页应用首屏优化实践
Jun 28 Javascript
解决JS表单验证只有第一个IF起作用的问题
Dec 04 Javascript
基于JavaScript 实现拖放功能
Sep 12 Javascript
详解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 的 __FILE__ 常量
2007/01/15 PHP
php数据库密码的找回的步骤
2011/01/12 PHP
浅析PHP原理之变量分离/引用(Variables Separation)
2013/08/09 PHP
Yii使用find findAll查找出指定字段的实现方法
2014/09/05 PHP
PHP defined()函数的使用图文详解
2019/07/20 PHP
php设计模式之备忘模式分析【星际争霸游戏案例】
2020/03/24 PHP
JS的IE和Firefox兼容性集锦
2006/12/11 Javascript
js tab 选项卡
2009/04/26 Javascript
将CKfinder整合进CKEditor3.0的新方法
2010/01/10 Javascript
Google Map V3 绑定气泡窗口(infowindow)Dom事件实现代码
2013/04/26 Javascript
jQuery往textarea中光标所在位置插入文本的方法
2015/06/26 Javascript
jQuery实现的隔行变色功能【案例】
2019/02/18 jQuery
微信小程序HTTP请求从0到1封装
2019/09/09 Javascript
ant design vue嵌套表格及表格内部编辑的用法说明
2020/10/28 Javascript
通过实例了解Render Props回调地狱解决方案
2020/11/04 Javascript
[47:03]完美世界DOTA2联赛PWL S3 access vs LBZS 第一场 12.20
2020/12/23 DOTA
Python数组条件过滤filter函数使用示例
2014/07/22 Python
Python调用命令行进度条的方法
2015/05/05 Python
Python读取图片属性信息的实现方法
2016/09/11 Python
python版简单工厂模式
2017/10/16 Python
Python程序退出方式小结
2017/12/09 Python
10 行 Python 代码教你自动发送短信(不想回复工作邮件妙招)
2018/10/11 Python
Pandas删除数据的几种情况(小结)
2019/06/21 Python
Python爬虫爬取、解析数据操作示例
2020/03/27 Python
python中pathlib模块的基本用法与总结
2020/08/17 Python
scrapy中如何设置应用cookies的方法(3种)
2020/09/22 Python
Python获取指定网段正在使用的IP
2020/12/14 Python
使用HTML5和CSS3表单验证功能
2017/05/05 HTML / CSS
html5 web本地存储将取代我们的cookie
2012/12/26 HTML / CSS
微信小程序canvas实现水平、垂直居中效果
2020/02/05 HTML / CSS
Java程序员面试题
2013/07/15 面试题
公司业务员岗位职责
2014/03/18 职场文书
一份教室追逐打闹的检讨书
2014/09/27 职场文书
乡镇司法所2015年度工作总结
2015/10/14 职场文书
python3 删除所有自定义变量的操作
2021/04/08 Python
SQL Server2019数据库备份与还原脚本,数据库可批量备份
2021/11/20 SQL Server