一劳永逸-支持本地打包后的history路由访问

背景

众所周知使用history路由模式的前端SPA项目,都需要额外进行服务器配置,像这样:

bash 复制代码
# nginx
location / {
  try_files $uri $uri/ /index.html;
}

# Apache
<IfModule mod_negotiation.c>
  Options -MultiViews
</IfModule>

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

# Caddy、Node等服务器

当项目足够多的时候,配置也会逐渐变得复杂起来、另外前端本地调试打包后的histroy路由页面时配置也比较麻烦。因此这里借助docker将配置文件生成镜像,后续需要调试本地history包时,就可以通过一个命令,一步到位。

下载docker

进入官网直接下载进好了:hub.docker.com/

终端输入docker -v,有版本号输出,说明已安装成功

配置

建个文件夹放通用的配置,这里就放两个文件Dockerfile、default.conf,也可以使用命令行生成

bash 复制代码
mkdir docker
cd docker
touch Dockerfile
touch default.conf

Dockerfile文件,用于生成镜像的配置文件:

csharp 复制代码
# 基于nginx创建镜像
FROM nginx

# 将default.conf文件复制到镜像中的nginx配置,这样相当于镜像中使用的本地配置文件
COPY default.conf /etc/nginx/conf.d/default.conf

default.conf文件

nginx的默认配置,放到镜像中后,所有前端项目可共用。这里只处理了打包后的dist和build文件夹

ini 复制代码
# 打包后的文件夹名为dist
server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    access_log  /var/log/nginx/host.access.log  main;
    error_log  /var/log/nginx/error.log  error;

    location / {
        root   /usr/share/nginx/html/dist;
        # root /var/lib/docker/volumes/my-volume/_data/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

# 打包后的文件夹名为build
server {
    listen       81;
    server_name  localhost;

    #charset koi8-r;
    access_log  /var/log/nginx/host.access.log  main;
    error_log  /var/log/nginx/error.log  error;

    location / {
        root   /usr/share/nginx/html/build;
        # root /var/lib/docker/volumes/my-volume/_data/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

基于配置创建镜像

终端执行:docker build -t docker-image-history-nginx .

命令说明:

  • docker build 创建镜像
  • -t 给镜像命名的参数
  • docker-image-history-nginx 镜像名
  • . 最后还有一个点说明是基于当前目录下的Dockerfile来创建镜像

创建后可以在docker桌面端看到刚创建的镜像:

基于镜像创建容器

创建容器后可以通过宿主机上的端口访问到容器中的端口、服务。

创建临时容器

终端执行:docker run --rm -it --name containerName -p 8888:80 imageName

临时容器会在退出终端后自动删除容器,适合本地调试、避免非必要的容器运行。

命令说明:

  • docker run 运行容器
  • --rm 当停止容器时自动清除该运行容器
  • -it 分配一个可交互的虚拟终端
  • --name 容器名的参数
  • containerName 自定义容器名
  • -p 端口映射的参数
  • 8888:80 宿主机端口:容器端口
  • imageName 创建容器使用的镜像所对应的名称

创建在后台运行的容器

终端执行:docker run -d -p 3000:80 --name containerName imageName

命令说明:

  • docker exec -it nginx sh # 进入容器环境中; exit退出容器环境
  • docker ps 查看运行中的容器
  • docker stop containerName 停止运行中的容器

注意: 如果提示这个,说明镜像已在使用中,端口已被占用。执行docker stop containerName就可以了

vbnet 复制代码
docker: Error response from daemon: driver failed programming external connectivity on endpoint build (8d8e73934d): Bind for 0.0.0.0:8765 failed: port is already allocated.

创建前端项目使用的临时容器

终端执行:

在项目根目录下执行

bash 复制代码
# 针对dist文件夹
docker run --rm -it -p 8765:80 --name dist -v "$(pwd)"/dist:/usr/share/nginx/html/dist docker-image-history-nginx

# 针对build 文件夹
docker run --rm -it -p 8765:81 --name build -v "$(pwd)"/build:/usr/share/nginx/html/build docker-image-history-nginx

命令说明:

  • -v 绑定挂载的参数
  • $(pwd) 可以获取到当前项目的绝对路径

以上可将本地的dist/build目录挂载到容器中Nginx下的dist/build目录下,此时就可以通过8765访问到容器中的dist/build文件 并 使用了镜像中的NGINX配置。

当然,这样使用很不合理,难道每次都要写这么长一串?显然不行,我们可以使用别名简化

bash 复制代码
alias docker_dist="docker run --rm -it -p 8765:80 --name dist -v "$(pwd)"/dist:/usr/share/nginx/html/dist docker-image-history-nginx"
alias docker_build="docker run --rm -it -p 8765:81 --name build -v "$(pwd)"/build:/usr/share/nginx/html/build docker-image-history-nginx"

后续只要在项目根目录下使用docker_distdocker_build命令即可。

使用梳理

  1. npm run build 打包
  2. 终端执行docker_distdocker_build
  3. 访问http://localhost:8765/about

总结

当然,如果只是为了实现这个功能大可不必这样折腾。这里只是提供一种思路,展示docker的一些能力,我们可以触类旁通实现更多需要的功能。

虽说大部分服务器都只支持静态文件的处理(如:budo、anywhere等),但也有一些提供了直接支持。如在终端执行:http-server --history-api-fallback

有了--history-api-fallback这个参数,http-server就会把所有不直接映射到文件的路由都重定向到index.html,从而支持HTML5 History API。browser-sync、lite-server轻量级服务器也能通过命令行直接支持。

也可以考虑使用 connect-history-api-fallback 中间件(配合express和koa框架)来实现同样的功能

相关推荐
半开半落3 分钟前
nuxt3安装pinia报错500[vite-node] [ERR_LOAD_URL]问题解决
前端·javascript·vue.js·nuxt
理想不理想v31 分钟前
vue经典前端面试题
前端·javascript·vue.js
不收藏找不到我32 分钟前
浏览器交互事件汇总
前端·交互
小阮的学习笔记1 小时前
Vue3中使用LogicFlow实现简单流程图
javascript·vue.js·流程图
YBN娜1 小时前
Vue实现登录功能
前端·javascript·vue.js
阳光开朗大男孩 = ̄ω ̄=1 小时前
CSS——选择器、PxCook软件、盒子模型
前端·javascript·css
minDuck1 小时前
ruoyi-vue集成tianai-captcha验证码
java·前端·vue.js
小政爱学习!1 小时前
封装axios、环境变量、api解耦、解决跨域、全局组件注入
开发语言·前端·javascript
魏大帅。1 小时前
Axios 的 responseType 属性详解及 Blob 与 ArrayBuffer 解析
前端·javascript·ajax