我真的不想要.html
起因 Coding
的旧版网站列表突然消失,以为要强制迁移新版
于是临时解析到了 Vercel,但是晚上它又好了
发现问题 但部署刷新几遍发现没有变化,当时德目录结构没有 live 文件夹里面放 index.html,会想到主页的.html
后缀问题,我去前往主页分页查看,果然不加.html
直接公益 404,那么就得为两种解析方式都准备好源文件
解决问题
主页怎么办
这是废话 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 const gulp = require ("gulp" );const minifycss = require ("gulp-clean-css" );const uglify = require ("gulp-uglify" );const htmlmin = require ("gulp-htmlmin" );const cssnano = require ("gulp-cssnano" );const htmlclean = require ("gulp-htmlclean" );const del = require ("del" );const babel = require ("gulp-babel" );const autoprefixer = require ("gulp-autoprefixer" );const connect = require ("gulp-connect" );const pug = require ("gulp-pug" );const sass = require ("gulp-sass" );const rename = require ("gulp-rename" );sass.compiler = require ("node-sass" ); const config = require ("./config.json" );gulp.task ("clean" , function ( ) { return del (["./dist/css/" , "./dist/js/" ]); }); gulp.task ("css" , function ( ) { return gulp .src ("./src/css/*.scss" ) .pipe (sass ().on ("error" , sass.logError )) .pipe (minifycss ({ compatibility : "ie8" })) .pipe (autoprefixer ({ overrideBrowserslist : ["last 2 version" ] })) .pipe (cssnano ({ reduceIdents : false })) .pipe (gulp.dest ("./dist/css" )); }); gulp.task ("html" , function ( ) { return gulp .src ("./dist/*.html" ) .pipe (htmlclean ()) .pipe (htmlmin ()) .pipe (gulp.dest ("./dist" )); }); gulp.task ("js" , function ( ) { return gulp .src ("./src/js/*.js" ) .pipe (babel ({ presets : ["@babel/preset-env" ] })) .pipe (uglify ()) .pipe (gulp.dest ("./dist/js" )); }); gulp.task ("pug" , function ( ) { return gulp .src ("./src/*.pug" ) .pipe (pug ({ data : config })) .pipe (gulp.dest ("./dist" )); }); gulp.task ("redirect" , function (done ) { config.redirect .forEach ((item ) => { let data = { redirect : item, count : config.count , template : item.template || "redirect" , }; gulp .src (`./src/redirect/${data.template} .pug` ) .pipe (pug ({ data : data })) .pipe (rename ("index.html" )) .pipe (gulp.dest (`./dist/${item.path} ` )); }); done (); }); gulp.task ("assets" , function ( ) { return gulp.src (["./src/assets/**/*" ]).pipe (gulp.dest ("./dist/assets" )); }); gulp.task ("staticHtml" , function ( ) { return gulp.src (["./src/*.html" ]).pipe (gulp.dest ("./dist" )); }); gulp.task ("test" , gulp.series ("redirect" )); gulp.task ("LICENSE" , function ( ) { return gulp.src (["./src/LICENSE" ]).pipe (gulp.dest ("./dist" )); }); gulp.task ("txt" , function ( ) { return gulp.src (["./src/*.txt" ]).pipe (gulp.dest ("./dist" )); }); gulp.task ("md" , function ( ) { return gulp.src (["./src/*.md" ]).pipe (gulp.dest ("./dist" )); }); gulp.task ("sw" , function ( ) { return gulp.src (["./src/*.js" ]).pipe (gulp.dest ("./dist" )); }); gulp.task ( "build" , gulp.series ( "clean" , "assets" , "staticHtml" , "pug" , "redirect" , "css" , "js" , "html" , "LICENSE" , "txt" , "md" , "sw" ) ); gulp.task ("default" , gulp.series ("build" )); gulp.task ("watch" , function ( ) { gulp.watch ("./src/components/*.pug" , gulp.parallel ("pug" )); gulp.watch ("./src/pages/*.pug" , gulp.parallel ("pug" )); gulp.watch ("./src/*.pug" , gulp.parallel ("pug" )); gulp.watch ("./src/css/**/*.scss" , gulp.parallel (["css" ])); gulp.watch ("./src/js/*.js" , gulp.parallel (["js" ])); connect.server ({ root : "dist" , livereload : true , port : 4000 , }); });
以上仅作为存档备份,万一哪天改没了,不想去找历史记录
最笨的方法解决 为了保险起见,我还是要确保双目录,境内外都能正常跳转
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 gulp.task ("about" , function ( ) { return gulp .src ("./dist/about.html" ) .pipe (rename ("index.html" )) .pipe (gulp.dest ("./dist/about" )); }); gulp.task ("link" , function ( ) { return gulp .src ("./dist/link.html" ) .pipe (rename ("index.html" )) .pipe (gulp.dest ("./dist/link" )); }); gulp.task ("speak" , function ( ) { return gulp .src ("./dist/speak.html" ) .pipe (rename ("index.html" )) .pipe (gulp.dest ("./dist/speak" )); }); gulp.task ("timeline" , function ( ) { return gulp .src ("./dist/timeline.html" ) .pipe (rename ("index.html" )) .pipe (gulp.dest ("./dist/timeline" )); }); gulp.task ("build" , gulp.series ("html" , "about" , "link" , "speak" , "timeline" ));
这样生成的文件目录和预期相同
但其实没必要这样麻烦,费力不讨好,改一改 gulpfile.js 这个文件生成文件的目录结构即可,或者往下看
结果 现在主页不管是Vercel
还是Coding
都能正常跳转脱掉.html
了,并且可实现境外境内分流,限制境外用户访问某些页面(伪操作
)
比如现在访问主站点直播界面,若是境外用户会显示(Vercel)
但境内用户则正常(Coding)
分析 在路由表默认逻辑上,Vervel
,Gitlab
,一致,Github
,Gitee``Coding
,Netlify
一致,所以上面的说法是不严谨的,用户可以在链接后加上.html
则可正常访问相应内容,但至少所有镜像站点都可以正常跳转了,然后配合 DNS 分流解析即可实现上面的效果
简单方式 查看 Vercel 官方文档 发现如下内容
Vercel uses Routes to define the behavior of how a request is handled by the routing layer. For example, you might use a Route to proxy a URL to another, redirect a client, or apply a header with the response to a request.
By default, routing is defined by the filesystem of your deployment. For example, if a user makes a request to /123.png
, and your [vercel.json](https://vercel.com/docs/configuration#project/routes)
file does not contain any routes with a valid src
matching that path, it will fallback to the filesystem and serve /123.png
if it exists.
NOTE: For Serverless Function routes, you can configure an /api
directory to provide filesystem routing and handle dynamic routing with path segments, without the need for configuration .
A Route can be defined within a project’s [vercel.json](https://vercel.com/docs/configuration#project/routes)
configuration file as an object within an array assigned to the routes
property, like the following which creates a simple proxy from one path to another:
1 2 3 { "routes" : [ { "src" : "/about" , "dest" : "/about.html" } ] }
An example vercel.json
file with a routes
property that proxies one path to another upon request.
Vercel Routes have multiple properties for each route object that help define the behavior of a response to each request to a particular path.
Type: String supporting PCRE Regex and Route Parameters like /product/(?<id>[^/]+)
.
For each route, src
is required to set the path which the behavior will affect.
The following example shows a vercel.json
configuration that takes a src
path and proxies it to a destination [dest](https://vercel.com/docs/configuration#dest)
path .
1 2 3 { "routes" : [ { "src" : "/about" , "dest" : "/about.html" } ] }
An example vercel.json
file with a routes
property that proxies one path to another upon request.
Type: String
dest
is used to proxy the [src](https://vercel.com/docs/configuration#src)
path to another path, such as another URL or Vercel hosted Serverless Function.
The example for the [src](https://vercel.com/docs/configuration#src)
property shows how both methods work together to create a proxy.
1 2 3 4 5 6 { "routes" : [ { "src" : "/about" , "dest" : "https://about.me" } , { "src" : "/action" , "dest" : "my-serverless-function-action/index" } ] }
An example vercel.json
file with routes
properties that proxy paths to another upon request.
NOTE: You can point the dest
path to any URL, Vercel hosted Serverless Function, or even non Vercel hosted URLs as shown in the code above. If you don’t perform any proxying, you can safely remove dest
.
1 2 3 { "routes" : [ { "src" : "/about" } ] }
This will route to /about
without proxying, but routes like this are usually redundant with handle filesystem .
这代表着我们可以按照上面的方式自定义路由表:即在根目录创建vercel.json
来完成自定义,并完美去掉.html
,解决这个问题,并且个人也是推荐这种更为简单的方法;而查看文档,我才发现 Vercel 真的是一个强大的静态托管平台,笔芯!
所以 Vercel 方面,以我主页为例,就可以通过以下代码来解决啦
1 2 3 4 5 6 7 8 { "routes" : [ { "src" : "/about" , "dest" : "/about.html" } , { "src" : "/link" , "dest" : "/link.html" } , { "src" : "/speak" , "dest" : "/speak.html" } , { "src" : "/timeline" , "dest" : "/timeline.html" } ] }