NuxtJS多域名 使用不同的域名访问不同的页面

通过路由模块(@nuxtjs/router)实现不同域名访问不同页面,不需要代理服务器。
本文是对文章 How to handle multiple domains and subdomains in your Nuxt.js project 的整理与扩充。原文章简单地介绍了实现方法,但不够详细,代码也存在死板与冗余。本文将说明原理,并提供通用解。

为急性子直接提供解决方案 详细解释在后文

首先,安装"@nuxtjs/router",保存为开发用模块:

npm install --save-dev @nuxtjs/router

/nuxt.config.js中引入:

  buildModules: [
    // 实际项目中可能不仅仅@nuxtjs/router模块,此处为示例
    [
      '@nuxtjs/router',
      {
        path: 'router',
        fileName: 'index.js',
        keepDefaultRouter: true,
      },
    ],
  ],

上方引入代码中pathfileName项指明了路由配置文件。在项目目录下建立/router/index.js文件。
文件内容:

import Vue from "vue";
import Router from "vue-router";

Vue.use(Router);

export function createRouter(ssrContext, createDefaultRouter, routerOptions) {
  const options = routerOptions || createDefaultRouter(ssrContext).options;
  let hostname = ssrContext ? ssrContext.req.headers.host : location.host;
  let group = /^([\w\.]+)(:\d+)?$/.exec(hostname);
  let domain = group ? group[1] : "";
  domain = doname.toLowerCase();

  return new Router({
    ...options,
    routes: formatRoutes(options.routes, domain)
  });
}

function formatRoutes(defaultRoutes, domain) {
  let routes = [];
  defaultRoutes.forEach(route => {
    if (!RegExp(`^\/${domain.replace(/\./, '\\.')}($|\\/.*)`).test(route.path))
      return;
    route.path = route.path.replace(new RegExp(`^\\/${domain}\\/?`), "/");
    routes.push(route);
  });
  return routes;
}

接下来只需要在/page文件夹下建立域名文件夹,以域名文件夹为域名对应根目录即可。
注意:域名是大小写无关的,但本文以小写形式匹配,因此域名文件夹需要全小写,否则无法正确匹配。
项目结构(此处仅展示改动部分,以实际项目为准):

project_root_dir
├── nuxt.config.js
├── package.json
├── pages
│   ├── a.b.chongying.studio
│   │   └── index.vue
│   ├── chongying.studio
│   │   └── index.vue
│   ├── other.chongying.club
│   │   └── index.vue
│   └── test.chongying.studio
│       └── index.vue
└── router
    └── index.js

接下来是详细解释

不过,需要说明的也就只有两个函数。

创建路由函数(createRouter):

通过调用默认方法来生成基础的路由,并将生成的路由交给格式化路由函数作进一步处理。

export function createRouter(ssrContext, createDefaultRouter, routerOptions) {
  // 获取默认的路由和主机名
  const options = routerOptions || createDefaultRouter(ssrContext).options;
  let hostname = ssrContext ? ssrContext.req.headers.host : location.host;
  // 使用正则提取主机名中不带端口的部分 即所需的域名
  let group = /^([\w\.]+)(:\d+)?$/.exec(hostname);
  let domain = group ? group[1] : "";
  // 转换为小写
  domain = domain.toLowerCase();

  return new Router({
    ...options,
    routes: formatRoutes(options.routes, domain)
  });
}

格式化路由函数(formatRoutes):

对默认路由进行筛选和处理。

function formatRoutes(defaultRoutes, domain) {
  let routes = [];
  defaultRoutes.forEach(route => {
    // 筛除 非此域名的路由
    if (!RegExp(`^\/${domain.replace(/\./, '\\.')}($|\\/.*)`).test(route.path))
      return;
    // 将路由路径的域名部分清除
    route.path = route.path.replace(new RegExp(`^\\/${domain}\\/?`), "/");
    routes.push(route);
  });
  return routes;
}

例如,存在以下路由:

/abc.chongying.studio
/abc.chongying.studio/abc
/abc.chongying.studio/abc/word
/def.chongying.club
/def.chongying.club/def
/def.chongying.club/def/word

当用户以’abc.chongying.studio访问时,路由将被处理为:

/
/abc
/abc/word

保留路径以"/abc.chongying.studio"开始的路由,并将路径中这部分前缀删除,即可得到正确的路由。

发表评论

邮箱地址不会被公开。 必填项已用*标注

CAPTCHAis initialing...