详解如何将 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 验证日期的函数
Mar 18 Javascript
Javascript数组的排序 sort()方法和reverse()方法
Jun 04 Javascript
jquery插件开发之实现google+圈子选择功能
Mar 10 Javascript
JavaScript动态改变表格单元格内容的方法
Mar 30 Javascript
微信内置浏览器私有接口WeixinJSBridge介绍
May 25 Javascript
快速掌握WordPress中加载JavaScript脚本的方法
Dec 17 Javascript
浅谈angular2 组件的生命周期钩子
Aug 12 Javascript
JavaScript程序设计高级算法之动态规划实例分析
Nov 24 Javascript
vue.js默认路由不加载linkActiveClass问题的解决方法
Dec 11 Javascript
d3.js实现自定义多y轴折线图的示例代码
May 30 Javascript
原生JS实现逼真的图片3D旋转效果详解
Feb 16 Javascript
Node.js事件的正确使用方法
Apr 05 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安全配置详细说明
2011/09/26 PHP
PHP使用CURL实现多线程抓取网页
2015/04/30 PHP
php双层循环(九九乘法表)
2017/10/23 PHP
JavaScript 操作键盘的Enter事件(键盘任何事件),兼容多浏览器
2010/10/11 Javascript
jquery 循环显示div的示例代码
2013/10/18 Javascript
结合JQ1.9通过js正则判断各种浏览器版本的方法
2013/12/30 Javascript
用JQuery实现全选与取消的两种简单方法
2014/02/22 Javascript
JavaScript中的定时器之Item23的合理使用
2015/10/30 Javascript
JavaScript保留关键字汇总
2015/12/01 Javascript
jquery自定义表单验证插件
2016/10/12 Javascript
微信小程序 网络请求(GET请求)详解
2016/11/16 Javascript
JS中with的替代方法与String中的正则方法详解
2016/12/23 Javascript
AngularJS Select(选择框)使用详解
2017/01/18 Javascript
Angualrjs 表单验证的两种方式(失去焦点验证和点击提交验证)
2017/05/09 Javascript
基于JS实现网页中的选项卡(两种方法)
2017/06/16 Javascript
微信小程序首页的分类功能和搜索功能的实现思路及代码详解
2018/09/11 Javascript
vue使用Google地图的实现示例代码
2018/12/19 Javascript
Vue两种组件类型:递归组件和动态组件的用法
2020/08/06 Javascript
[45:38]DOTA2上海特级锦标赛主赛事日 - 1 胜者组第一轮#1Liquid VS Alliance第一局
2016/03/02 DOTA
python3使用requests模块爬取页面内容的实战演练
2017/09/25 Python
Python实现打印螺旋矩阵功能的方法
2017/11/21 Python
python TCP Socket的粘包和分包的处理详解
2018/02/09 Python
pyinstaller打包单文件时--uac-admin选项不起作用怎么办
2020/04/15 Python
利用python控制Autocad:pyautocad方式
2020/06/01 Python
python如何导入依赖包
2020/07/13 Python
python对输出的奇数偶数排序实例代码
2020/12/04 Python
HTML5拖拽API经典实例详解
2018/04/20 HTML / CSS
意大利团购网站:Groupon意大利
2016/10/11 全球购物
CHARLES & KEITH澳大利亚官网:新加坡时尚品牌
2019/01/22 全球购物
Myprotein荷兰官网:欧洲第一运动营养品牌
2020/07/11 全球购物
数控技术与应用毕业生自荐信
2013/09/24 职场文书
母亲追悼会答谢词
2014/01/27 职场文书
模具专业自荐信
2014/05/29 职场文书
行政处罚决定书
2015/06/24 职场文书
公司财务制度:成本管理控制制度模板
2019/11/19 职场文书
Win11显卡控制面板打开显卡设置方法
2022/04/20 数码科技