You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Angular Universal中配置express-useragent传递UA信息

Angular Universal 集成 express-useragent 并在框架内获取设备信息

步骤1:安装依赖

先安装express-useragent及其TypeScript类型定义:

npm install express-useragent --save
npm install @types/express-useragent --save-dev

步骤2:配置 server.ts

你可以直接引入并使用express-useragent中间件,核心是把解析后的设备信息通过Angular Universal的渲染参数传递到框架内部。修改server.ts如下:

import * as express from 'express';
import * as useragent from 'express-useragent';
import { ngExpressEngine } from '@nguniversal/express-engine';
import { AppServerModule } from './src/main.server';
import { APP_BASE_HREF } from '@angular/common';
import { existsSync } from 'fs';
import { join } from 'path';

export function app(): express.Express {
  const server = express();
  const distFolder = join(process.cwd(), 'dist/your-project-name/browser');
  const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';

  // 启用用户代理解析中间件
  server.use(useragent.express());

  // 配置Angular SSR引擎
  server.engine('html', ngExpressEngine({
    bootstrap: AppServerModule,
  }));

  server.set('view engine', 'html');
  server.set('views', distFolder);

  // 处理静态资源
  server.get('*.*', express.static(distFolder, { maxAge: '1y' }));

  // 处理所有路由,传递设备信息到Angular
  server.get('*', (req, res) => {
    // 提取需要的用户代理字段
    const deviceInfo = {
      isMobile: req.useragent.isMobile,
      isDesktop: req.useragent.isDesktop,
      isTablet: req.useragent.isTablet,
      browser: req.useragent.browser,
      os: req.useragent.os
    };

    res.render(indexHtml, {
      req,
      res,
      providers: [
        { provide: APP_BASE_HREF, useValue: req.baseUrl },
        // 将设备信息注入Angular依赖系统
        { provide: 'DEVICE_INFO', useValue: deviceInfo }
      ]
    });
  });

  return server;
}

function run(): void {
  const port = process.env['PORT'] || 4000;
  const server = app();
  server.listen(port, () => {
    console.log(`Node Express server listening on http://localhost:${port}`);
  });
}

run();

步骤3:创建类型安全的注入令牌(可选但推荐)

为了避免直接使用字符串标识导致的类型问题,在Angular项目中创建注入令牌:

// src/app/core/device-info.token.ts
import { InjectionToken } from '@angular/core';

export interface DeviceInfo {
  isMobile: boolean;
  isDesktop: boolean;
  isTablet: boolean;
  browser: string;
  os: string;
}

export const DEVICE_INFO = new InjectionToken<DeviceInfo>('DEVICE_INFO');

之后在server.ts的providers中替换为这个令牌:

{ provide: DEVICE_INFO, useValue: deviceInfo }

步骤4:在 app-routing.module.ts 中获取设备信息

通过Angular的依赖注入,就能在路由模块或路由守卫中获取设备信息:

import { NgModule } from '@angular/core';
import { RouterModule, Routes, CanActivate } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { DEVICE_INFO, DeviceInfo } from './core/device-info.token';
import { Inject } from '@angular/core';

// 示例:路由守卫中使用设备信息
export class DeviceCheckGuard implements CanActivate {
  constructor(@Inject(DEVICE_INFO) private deviceInfo: DeviceInfo) {}

  canActivate() {
    console.log('当前设备是否为移动端:', this.deviceInfo.isMobile);
    // 可根据设备类型执行路由拦截或重定向逻辑
    return true;
  }
}

const routes: Routes = [
  { path: '', component: HomeComponent, canActivate: [DeviceCheckGuard] }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [DeviceCheckGuard]
})
export class AppRoutingModule {
  // 直接在模块构造函数中获取设备信息
  constructor(@Inject(DEVICE_INFO) private deviceInfo: DeviceInfo) {
    console.log('路由模块初始化时获取的设备信息:', this.deviceInfo.isDesktop);
  }
}

关键说明

  • 你的初始思路是可行的:直接引入express-useragent解析请求头,核心是通过res.render的providers参数把数据注入Angular依赖系统,确保SSR渲染前框架能拿到设备信息。
  • 每个请求的设备信息都是独立的,不会出现跨请求数据污染,因为res.render会为每个请求创建新的注入上下文。
  • 客户端环境下(比如前端路由跳转),需要额外通过window.navigator.userAgent解析设备信息,可封装一个服务统一处理服务端/客户端的设备逻辑。

内容的提问来源于stack exchange,提问作者Murmulodi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 22:20:35