vue build本地预览与路由History模式下页面空白

用vue-cli开发的项目在开发完打包之后想在本地预览要怎么做呢?这里要根据你的路由模式来分两种情况 1. history 模式 2. hash 模式(默认情况下)
我们先来说问题场景和解决方法。

如何预览:
方法1 : 项目根目录dist 文件夹下的 index.html 文件直接用浏览器打开。
方法2 : 在本地搭建一个服务器,然后运行该打包后的静态资源。

方法1

方法1 预览遇到问题:
用方法1 预览时,如果可能会遇到打开页面为空白的情况。

如何解决:
情况 1: 路由模式 mode: hash
其实这跟配置资源的路径有关,打开项目根目录config文件夹下的index.js,定位到build下的assetsPublicPath(dev下也有一个assetsPublicPath,别搞错了),把assetsPublicPath: '/' 修改为相对路径 assetsPublicPath: './'
修改完之后重新打包,然后用方法1来预览

情况 2: 路由模式 mode: history
只能用方法2来预览。


方法2

用node 或 express 打开一个本地服务器端口来预览打包后的静态文件。

当用方法2来预览时 assetsPublicPath 为相对路径或绝对路径都没影响。

因为vue项目为脚手架搭建的已经有 node 和 express 依赖,无需重新安装。我们可以直接在根目录下新建一个 js 文件, 因为是开启服务器的配置,一般会习惯性的命名为server.js,配置如下:

const express = require("express")
const app = express()

const port = 8081

app.use(express.static('./dist'))

app.listen(port, () => {
  console.log('Listening at http://localhost:' + port)
})

根目录下用node命令开启一个 8081 的端口来监听该运行:node server.js
监听成功后再浏览器输入: http://localhost:8081
就能看到项目页面了。

方法2 预览遇到问题:
如果 路由模式 hash 就万事大吉了,但为 history 时你会发现
此时只要首页能访问,通过首页点进去其他路由也是可以的,但是如果在其他路由刷新就有错误了,必须回到首页重新刷新才能正常访问。

如何解决:
上面的server.js 配置需加多加 connect-history-api-fallback 该中间件的作用是当页面访问出现错误时重定向到 index.html 页面,既重新访问index.html。配置如下:

const express = require("express")
const app = express()

const port = 8081

let history = require('connect-history-api-fallback')

//重定向到index.html
history({
  rewrites: [{
      from: /^\/libs\/.*$/,
      to: '/index.html'
    }]
});

app.use(history());

app.use(express.static('./dist'))

app.listen(port, () => {
  console.log('Listening at http://localhost:' + port)
})

修改完配置后,重新启动服务器(重新执行node server.js) 命令,然后在浏览器访问,就不会出现上面访问错误的情况了。
此时如果你的路由有设置通配符到404页面的话,如下

const router = new VueRouter({
  mode: 'history',
  routes: [
    { path: '*', component: NotFoundComponent }
  ]
})

当url输入的为错误地址时,就会跳转到 NotFoundComponent 页面,然后输入正确的地址又可以访问。

我们执行的vue 命令 都是 npm run xx 的,那么启动我们的本地预览服务器能不能用这种类型的命令呢?当然是可以的。
先来看看根目录下的 package.json文件 的 scripts

 "scripts": {
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "start": "npm run dev",
    "build": "node build/build.js"
}

这里的 dev start build 是不是很熟悉,我们只想的 npm run xxx 命令就是根据这里的字段来运行的。
来看看 build 指向的是build/build.js 文件。
那我们想运行npm run server 这样的命令来启动本地预览服务器设置可以是:
1.在 scripts 下新增 "server": "node build/server.js"
2.把刚才创建在根目录下的 server.js 文件 移动到 build 文件夹下。
3.根目录下运行 npm run server




原理

上面说了问题及解决方法,这里来说说为什么会出现上面的问题及问题的所在和怎么去定位问题。

** hash 模式下静态资源访问错误问题:**

方法1直接访问dist下的index.html文件时静态资源错误 assetsPublicPath 的路径问题。

image.png

打开控制台会发现,script标签的引入路径不对,因为static文件夹和index.html是在同一个目录下的,这里却是从根目录引入static下的文件,正确的路径应该是./开头的相对路径:
src='./static/...' 或者 src='static/...'
问题已经确定,是打包后的文件路径有问题

于是就去找webpack.base.conf.js文件,有个output选项,output是webpack中对输出文件的配置,最常用的有fileName、path属性,指定输出文件的名称和在项目中的位置,publicPath可以为项目中的所有资源指定一个基础路径,也是我们解决这个问题的关键。

webpack.base.conf.js

可以看到 publicPath 属性的值是根据 process.env.NODE_ENV 来判断的。那 process.env.NODE_ENV 又是什么呢?

process对象 是一个全局对象,可以在应用程序中全局使用(包括在业务页面);
process.env 属性返回一个包含用户环境信息的对象;
process.env.NODE_ENV 用来定义环境变量,一般包括production(生产环境)、development(开发环境),webpack中各种配置都是根据环境变量的不同来做相应的处理的。

从三元中知道 打包后(production 生产环境) 的 publicPath 是由 config.build.assetsPublicPath 来决定的,那我们就找到 config 文件夹下的index.js文件,然后定位到 build 下的 assetsPublicPath。
既然是 加载的文件引入路径错误的原因,那把引入路径修改过来就可以啦,既把 assetsPublicPath: '/' 修改为 assetsPublicPath: './'

history 模式下本地服务器在除根路由外其他路由刷新页面后找不到路径

history 和 hash 模式有什么区别呢?

history 模式是h5 api 的 history.pushState ,相对于浏览器模拟了一条历史,而真正的服务器上没有这个路径资源,为什么 hash 模式没有这个问题?
hash 模式是带# 符号,服务器就不会解析,相对于还是返回html而已, index.html会根据vue路由去解析;
而在 history 模式下,只是动态的通过js 操作window.history 来改变有浏览器地址栏里的路径,并没有发起http请求,但当你直接在浏览器里输入这个地址的时候 就一定要先对服务器放起http请求,但是这个目标在服务器上又不存在所以就返回了404了,怎么解决呢,就是把所有的请求全部转发到 index.html,让 index.html 重新取匹配路由。

对于浏览器的这种机制 vue-router 官方也给出了多种解决方案。
上面方法2使用中间件 connect-history-api-fallback 的方案实质上当找不到路由时重定向回项目首页,既

在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。


history 模式下项目放在服务器子目录下访问为空白页面问题。

经过上面的方法2 基本上是没什么问题了(上面server.js配置中项目是部署在服务器根目录下的),但是在实际开发中,项目可能是部署在子目录下的。
此时若开启了 history 模式,在dev开发阶段是没问题的,但是打包之后部署在服务器根目录下,即把打包后生成的dist文件夹(不要上传文件夹)里的内容上传到服务器上,访问路径为:
xxx.com
此时访问正常。

但如果是部署在服务器子路下呢?例如放在子目录 public下,访问路径为:
xxx.com/public/
此时访问为空白页,这也是引用资源路径问题。
此时服务器上的目录结构是

www/
 +public/
   +static/
   +index.html

但是上面说过,index.htmlapp.js 的引用方式是

<script type="text/javascript" src="/static/js/app.js"></script>

index.html引用app.js 的路径是 http://www.xxx.com/static/js/app.js
而部署在 public 文件夹下时,app.js 的实际路径是 http://www.xxx.com/public/static/js/app.js

所以当你通过http://www.xxx.com/public/index.html来访问的时候会出现找不到app.js

要解决的方法很简单把引用方式 改成如下两种方式都可以

<script type="text/javascript" src="./static/js/app.js"></script>
// 或者
<script type="text/javascript" src="/public/static/js/app.js"></script>

可以是 修改webpack 位置

assetsPublicPath: './'
或者
assetsPublicPath: '/public/',

或者配置路由 routerbase 属性, 设置为子目录路径即可

export default new Router({
  mode: 'history',
  base: '/public/', 
routes: []
})

重启服务器,就可以用 xxx.com/public/ 访问了。



参考:
直接打开 打包后文件 404 解决方法
Vue-router的使用姿势

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 197,814评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,124评论 2 375
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 144,814评论 0 327
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,924评论 1 268
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,815评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,562评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,944评论 3 388
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,582评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,859评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,881评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,700评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,493评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,943评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,115评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,413评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,978评论 2 343
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,182评论 2 339

推荐阅读更多精彩内容