字节笔记本字节笔记本

Next.js 实现环境变量配置和模块路径优化

2024-06-06

本文介绍了如何在Next.js项目中配置环境变量和优化模块路径,包括使用.env文件加载环境变量、在浏览器中获取环境变量、设置默认环境变量、测试环境变量以及使用绝对地址导入和模块路径别名。

环境变量配置

.env.local 加载环境变量

  1. 创建 .env.local 文件

    • 在项目根目录下创建 .env.local 文件(注意是根目录,不是 /src 目录)
    DB_HOST=localhost
    DB_USER=myuser
    DB_PASS=mypassword
    
  2. 在代码中使用环境变量

    // app/page.js
    export default function Page() {
      console.log(process.env.DB_HOST);
      return <h1>Hello World!</h1>;
    }
    
    // app/api/route.js
    export async function GET() {
      const db = await myDB.connect({
        host: process.env.DB_HOST,
        username: process.env.DB_USER,
        password: process.env.DB_PASS,
      });
      // ...
    }
    
  3. 多行变量

    # .env.local
    
    # 直接换行
    PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
    ...
    Kh9NV...
    ...
    -----END DSA PRIVATE KEY-----"
    
    # 使用 `\n`
    PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nKh9NV...\n-----END DSA PRIVATE KEY-----\n"
    
  4. 引用其他变量

    TWITTER_USER=nextjs
    TWITTER_URL=https://twitter.com/$TWITTER_USER
    

浏览器中获取环境变量

  1. 添加 NEXT_PUBLIC_前缀

    • 在 .env.local 文件中添加变量
    NEXT_PUBLIC_ANALYTICS_ID=abcdefghijk
    
  2. 在代码中使用环境变量

    'use client';
    // app/page.js
    export default function Page() {
      return <h1 onClick={() => {
        console.log(process.env.NEXT_PUBLIC_ANALYTICS_ID);
      }}>Hello World!</h1>
    }
    
  3. 动态查找值

    // 动态查找不会被内联,不会生效
    const varName = 'NEXT_PUBLIC_ANALYTICS_ID';
    setupAnalyticsService(process.env[varName]);
    
    const env = process.env;
    setupAnalyticsService(env.NEXT_PUBLIC_ANALYTICS_ID);
    

默认环境变量

  1. 在不同环境中设置默认值

    • .env(所有环境)
    • .env.development(开发环境)
    • .env.production(生产环境)
    • .env.local 会覆盖这些默认值
    • 注意添加 .env.local 到 .gitignore中
  2. 默认 NODE_ENV 值

    • next dev:NODE_ENV 赋值为 development
    • 其他命令:NODE_ENV 赋值为 production

测试环境变量

  1. 创建 .env.test 文件
    • 测试环境不会加载 .env.local 中的值
    • NODE_ENV 设置为 test 时使用

环境变量加载顺序

  1. 查找顺序
    • process.env
    • .env.$(NODE_ENV).local
    • .env.local(NODE_ENV 为 test 时不会查找)
    • .env.$(NODE_ENV)
    • .env

绝对地址导入和模块路径别名

绝对地址导入

  1. 配置 baseUrl

    // tsconfig.json or jsconfig.json
    {
      "compilerOptions": {
        "baseUrl": "."
      }
    }
    
  2. 使用示例

    // components/button.js
    export default function Button() {
      return <button>Click me</button>;
    }
    
    // app/page.js
    import Button from '/components/button';
    
    export default function HomePage() {
      return (
        <>
          <h1>Hello World</h1>
          <Button />
        </>
      );
    }
    

模块别名

  1. 配置 paths

    // tsconfig.json or jsconfig.json
    {
      "compilerOptions": {
        "baseUrl": ".",
        "paths": {
          "@/components/*": ["components/*"]
        }
      }
    }
    
  2. 使用示例

    // components/button.js
    export default function Button() {
      return <button>Click me</button>;
    }
    
    // app/page.js
    import Button from '@/components/button';
    
    export default function HomePage() {
      return (
        <>
          <h1>Hello World</h1>
          <Button />
        </>
      );
    }
    
  3. baseUrl 和 paths 关系

    // tsconfig.json or jsconfig.json
    {
      "compilerOptions": {
        "baseUrl": "src/",
        "paths": {
          "@/styles/*": ["styles/*"],
          "@/components/*": ["components/*"]
        }
      }
    }
    
  4. 使用示例

    // pages/index.js
    import Button from '@/components/button';
    import '@/styles/styles.css';
    import Helper from 'utils/helper';
    
    export default function HomePage() {
      return (
        <Helper>
          <h1>Hello World</h1>
          <Button />
        </Helper>
      );
    }
    

使用 src 目录

  1. 代码结构调整

    • 将代码移动到 src/app 或 src/pages
    • /public 目录放在项目根目录
    • package.json、next.config.js、tsconfig.json 等配置文件放在项目根目录
    • .env.* 文件放在项目根目录
    • 根目录存在 app 或 pages 时,src/app 或 src/pages 会被忽略
    • 移动其他应用文件夹如 /components 或 /lib
    • 中间件放在 src 目录下
  2. 修改 Tailwind CSS 配置

    /** @type {import('tailwindcss').Config} */
    module.exports = {
      content: [
        './src/**/*.{html,js}',
      ],
      // ...
    }