nuxt3拆包剖析——配置加载

689 阅读4分钟

前言

在使用nuxt3的过程中,我会很好奇nuxt3nuxt.config.ts配置加载是如何做到的,查看源码,发现了一个很有意思的工具——c12,接下来我们来讲解下这个工具的用法。

c12

Smart Configuration Loader.

点击链接跳到工具仓库

通过README.md可以看到,该工具能够做到:

  • 解析JSON, CJS, TS, ESM格式的config
  • 解析RC配置
  • 重复配置的合并
  • 解析.env配置
  • 解析package.json配置
  • 配置监听器

以上几个功能足以应付目前市面上绝大多数的配置处理

使用方法

这是代码仓库,直接clone代码下来运行即可

主要使用代码:

import { loadConfig } from 'c12'

(async () => {
  const config = await loadConfig({
    name: 'wu',
  })

  console.log(config)
})()

当本地没有配置文件的时候,运行结果如下:

{
  config: {},
  cwd: 'D:/project/nuxt-c12-demo',
  configFile: 'D:/project/nuxt-c12-demo/wu.config',
  layers: [ { config: {}, configFile: '.wurc' } ]
}

在本地创建wu.config.js wu.config.ts wu.config.json

image.png

image.png

image.png

通过name属性区分读取的是哪个文件,以下是输出结果

{
  config: { name: 'wu-js', age: 18, male: true },
  cwd: 'D:/project/nuxt-c12-demo',
  configFile: 'D:\\project\\nuxt-c12-demo\\wu.config.js',
  layers: [
    {
      config: [Object],
      configFile: 'wu.config',
      cwd: 'D:/project/nuxt-c12-demo'
    },
    { config: {}, configFile: '.wurc' }
  ]
}

可以看到,当以上三种格式同时存在时,会优先读取js文件

其他格式配置读取

RC配置

我们创建.wurc配置

image.png

运行结果:

config: {
    wurc: true,
    'wurc-only': 'hhh',
    wurcOnlyToo: 'xxx',
    name: 'wu-js',
    age: 18,
    male: true
},

全局RC配置

我用的是win11,macos的全局配置在哪我不清楚,你们可以自行查阅

win用户的全局配置在C:/User/xxxx(用户名)/,创建一个.wurc(以后不用了记得删)

image.png

注意,读取全局配置,我们还需要设置globalRc属性为true

import { loadConfig } from 'c12'

(async () => {
  const config = await loadConfig({
    name: 'wu',
    globalRc: true,
  })

  console.log(config)
})()

运行结果如下

config: {
    wurcGlobal: true,
    'wurc-global-only': 'hhh',
    wurc: true,
    'wurc-only': 'hhh',
    wurcOnlyToo: 'xxx',
    name: 'wu-js',
    age: 18,
    male: true
},

package.json

想偷懒的同学也可以直接把配置放在package.json中,不过个人不是很建议这样处理,这样会污染package.json,不利于多人协作后续交接

我们修改package.json

image.png

同时需要注意,使用package.json也需要设置配置packageJson为true

import { loadConfig } from 'c12'

(async () => {
  const config = await loadConfig({
    name: 'wu',
    globalRc: true,
    packageJson: true,
  })

  console.log(config)
})()

运行结果:

config: {
    package: true,
    packageOnly: 'xxx',
    wurcGlobal: true,
    'wurc-global-only': 'hhh',
    wurc: true,
    'wurc-only': 'hhh',
    wurcOnlyToo: 'xxx',
    name: 'wu-js',
    age: 18,
    male: true
},

默认配置

我们还可以配置默认配置,使用defaults属性

需要注意的是,defaults属性配置的默认参数,是最低优先级的

import { loadConfig } from 'c12'

(async () => {
  const config = await loadConfig({
    name: 'wu',
    globalRc: true,
    packageJson: true,
    defaults: {
      name: 'defaults',
      defaultKey: 'defaultValue',
    },
  })

  console.log(config)
})()

运行结果如下

config: {
    name: 'wu-js',
    defaultKey: 'defaultValue',
    package: true,
    packageOnly: 'xxx',
    wurcGlobal: true,
    'wurc-global-only': 'hhh',
    wurc: true,
    'wurc-only': 'hhh',
    wurcOnlyToo: 'xxx',
    age: 18,
    male: true
},

可以看到,我们配置了默认参数namedefaultKey,由于已经有了name属性,所以默认配置并不会生效

env配置,特别注意

我在尝试读取.env配置的时候,发现即使配置了dotenv: true,还是没有读取配置

查阅了源码,发现源码并没有合并env配置,不知道有意为之还是疏忽,这里我提了个issue,有这方面需求的同学可以关注一下

不过c12提供了单独读取env配置的api——loadDotenv

import { loadConfig, loadDotenv } from 'c12'

const env = await loadDotenv({
    cwd: '.',
    fileName: '.env',
})

console.log(env)

image.png

结果如下

[Object: null prototype] {
  DOTENV: 'true',
  DOTENVONLY: 'QQQ',
  _applied: true
}

更新:这里的处理结果请看我发的评论

监听配置修改

c12还提供了一个有意思的功能,能够监听配置文件的修改并执行回调,这里是封装了chokidar

api是watchConfig,跟loadConfig用法类似,多了几个入参,控制回调方法

import { watchConfig } from 'c12'

const config = await watchConfig({
    cwd: '.',
    name: 'wu',
    onWatch: (event) => {
      console.log('[watcher]', event.type, event.path)
    },
    acceptHMR({ oldConfig, newConfig, getDiff }) {
      const diff = getDiff()
      if (diff.length === 0) {
        console.log('No config changed detected!')
        return true // No changes!
      }
    },
    onUpdate({ oldConfig, newConfig, getDiff }) {
      const diff = getDiff()
      console.log(`Config updated:\n${diff.map(i => i.toJSON()).join('\n')}`)
    },
})

console.log(config)

image.png

可以看到,运行时会先输出监听的文件列表

image.png

修改配置文件,也能触发回调方法

该方法可以用于,监听配置文件是否修改,进行系统restart处理等操作

总结

nuxt3使用unjs/c12来进行配置处理,该工具提供了多种配置读取方式,并且具有监听配置修改触发回调等操作

我们在开发类似配置读取功能的时候也可以使用该工具,简单易上手