关于前端部署后出现 跨域问题 和 页面出现404的问题总结

2,095 阅读6分钟

关于前端部署后,出现一些跨域问题和页面出现404的问题汇总:

开发时态由webpack-dev-server开启的服务器,可以看做是nginx静态服务器理解(做的事是一样的);做两件事1. 提供index.html静态资源, 2.对请求接口进行代理转发。 区别:webpack-dev-server是在内存总处理的即(webpack没有打包成为资源)。而nginx是将打包后的真实资源进行了部署(打包后将dist,赋值到指定的配置目录即可)

情况1:静态服务器可以做代理转发

开发环境:

  • 静态资源

开启服务为localhost:3000 --> dev-server返回index.html --> 浏览器解析执行。

浏览器解析执行html后 --> 执行js中的ajax请求,接口为 '/news/info'

常见操作1.开发时填写完整的地址 http://www.app1.com/news/info 
localhost:3000
www.app1.com 
两者存在跨域问题

常见操作2.开发时请求地址为 /news/info
localhost:3000/news/info(由于没有写具体的主机和端口号,浏览器会自动使用地址栏的)
请求不到数据
  • 引入代理proxy

静态资源不受影响

数据接口api中,如果接口中匹配到 "/news/",浏览器会自动拼接主机地址[即静态资源部署服务地址]/news/info 会被代理到 www.app1.com/news/info , 服务端间的请求是不存在跨域问题的。

    // 具体配置详见webpack https://webpack.js.org/configuration/dev-server/#devserverproxy
    devServer: {
    host: "0.0.0.0",
    port: port,
    open: true,
    proxy: {
      "/news/": {
        target: `http://www.app1.com`, 
        changeOrigin: true,
      },
    },
    disableHostCheck: true,
  },

生成环境(打包后):

部署到www.app1.com (部署,就是将打包后的资源文件,放置在服务器指定的配置路径下)

静态资源

访问www.app1.con --> 静态服务器,将打包后的 html文件返回 --> 浏览器展示没问题。

数据资源 www.data.com/news

浏览器解析执行html后 --> 执行js中的ajax请求,接口为 '/news/info' , 即会访问 www.app.com/news/info, 此时就需要nginx进行proxy代理配置:

    
    server {
        listen 80; // 端口
        server_name http://www.app1.com; 
        
        # 具体的nginx的代理规则,自行搜索文章视频学习; 这里仅仅说明.
        location /news { 
            proxy: http://www.data.com // 数据服务地址
        }
    }
    

有关 publicPah 的配置场景

一个大型项目,分为不同板块进行开发。例如:新闻板块、游戏板块等在同一个静态资源服务器地址的不同路径下:

新闻板块: www.app1.com/news 资源包放置在news文件下 游戏板块: www.app1.com/games 资源包放置在games文件下

server {
    listen 80;
    server_name www.app1.com;

    # 配置新闻板块
    location /news {
        alias /news;  # 这里的路径请根据你的实际资源包存放路径修改
        index index.html;
        try_files $uri $uri/ /news/index.html;
    }

    # 配置游戏板块
    location /games {
        alias /games;  # 这里的路径请根据你的实际资源包存放路径修改
        index index.html;
        try_files $uri $uri/ /games/index.html;
    }

    # 处理其他请求(例如网站根目录的请求)
    location / {
        root /root;
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    error_page 404 /404.html;
    location = /404.html {
        root /var/www/html;
    }
}

如果不配置 publicPath

默认配置 '/', html中生成的静态文件引入如下

经webpack打包之后,html如下:
...
<link ref="/css/xxxx.css">
...

那么,
1.当访问新闻板块 http://www/app1.com/news, 静态服务返回html
2.解析执行到 <link ref="/css/xxxx.css"> 就会请求 www.app1.com/css/xxxx.css(浏览器会自动拼接),此时路径在nginx端, 没有匹配到 news 前缀, 它进入到 / 即root文件下, 但root下并不是我们存放新闻模块的文件路径. 即可能不存在报 404.

解决问题

利用publicPath,例如: 新闻板块 publicPath:'news'

经webpack打包之后,html如下:
...
<link ref="/news/css/xxxx.css">
<script src="/news/js/xxxx.js"> </script>
...

那么,
1.当访问新闻板块 http://www/app1.com/news, 静态服务返回html
2.解析执行到 <link ref="/news/css/xxxx.css"> 就会请求 www.app1.com/news/css/xxxx.css(浏览器会自动拼接),那么就被nginx配置news匹配到, 从news文件路径下找资源css/xxxx.css, 是我们存放新闻模块的地方,存在并且返回.

影响问题2

publicPath配置后, 影响打包资源存放路径, 那么进而影响访问资源的路由, 找不到显示自定义404页面

publicpath 默认为 / 时, 资源就在 nginx 配置 / 对应的资源路径下, 路由为 /create 访问创建页. publicpath 改变为 /news后, 资源被换到 /news 对应的资源路径下, 要想访问到, 必须加前缀 /news+路由 即 /news/create. 但原始路由运行时路径可是 /create 故此时路由配置中不存在 /news/create. 故回报404.

因此, 必须同时修改route的初识配置选项:

router配置对象中 base: '/news'(可以使用前面说的process.env.BASE_URL), 告诉路由我们的基地址是news。给路由配置, 统一添加 news 前缀.

情况2:静态服务器由于某种原因,不允许代理转发

静态资源服务:www.app1.com

测试数据服务:www.testserver.com

生产数据服务:www.prodserver.com

在开发中,接口地址为 /info

  1. 使用前面的方式,开发时proxy,没有问题因为可以代理。但是打包之后,静态服务不做代理,那么这种就必然会重载跨域问题。(不可行

  2. 只能将地址写死在接口里面 开发中很少这样

    2.1 需要解决跨域问题:需要解决跨域问题(jsonp、cros、服务器端设为支持跨域), 后端帮忙处理.

    2.2 维护性问题 / 资源地址暴露安全问题,往往这种情况很少出现.

    2.3 如果时第三方开放平台, 后端无法接入/公开; 为了提高维护性, 使用环境变量, 如下 第6 :

    //利用环境变量。参考:https://cli.vuejs.org/zh/guide/mode-and-env.html#%E6%A8%A1%E5%BC%8F
    
    1. 只有node环境下有process, 为什么在代码中写入process.env.xxx 开发环境和生产环境即打包后执行不报错呢?
    答案:vue-cli基于webpack, 利用webpack.definePlugin插件,在打包过程中扫描代码中的 process.env.xxx 进行了value值得替换。
    
    2. 是如何做到的呢,vuecli中介绍,使用了dotenv插件。
    想要了解解析环境文件规则的细节,请参考 [dotenv](https://github.com/motdotla/dotenv#rules)。我们也使用 [dotenv-expand](https://github.com/motdotla/dotenv-expand) 来实现变量扩展 (Vue CLI 3.5+ 支持)。
    
    3. 配置文件中的process是读取,因为配置文件是在webpack打包过程直接参与运行的(node环境)。
    
    4. 环境变量说明:
    process.env.NODE_ENV 不要改动脚手架内部在控制NODE_ENV的变化
    process.env.BASE_URL 也不要随意改动,与publicPath相关联,读取配置文件执行中,将publicPath赋值为它。
    process.VUE_APP_* 可以根据开发需求自行定义的环境变量
    
    用于定义环境变量的文件:参阅vue-cli
    .env
    .env.production 定义VUE_APP_SERVERURL = www.prodserver.com
    .env.devolpment 定义VUE_APP_SERVERURL = www.testserver.com
    
    5. 环境文件加载优先级
        5.1 为一个特定模式准备的环境文件 (例如 `.env.production`) 将会比一般的环境文件 (例如 `.env`) 拥有更高的优先级。

        5.2 此外,Vue CLI 启动时已经存在的环境变量拥有最高优先级,并不会被 `.env` 文件覆写。
        
        5.3 `.env` 环境文件是通过运行 `vue-cli-service` 命令载入的,因此环境文件发生变化,你需要重启服务。
   
    6. 解决上面的问题:
    定义两个环境文件
    .env.production 文件 定义VUE_APP_SERVERURL = www.prodserver.com
    .env.devolpment 文件 定义VUE_APP_SERVERURL = www.testserver.com
    
    在axios中,将 baseUrl:VUE_APP_SERVERURL 即可。以及其他使用的地方用 VUE_APP_SERVERURL 替换。
    
    

下班!