一个 Webpack loader,用于从 JSON 文件中按键名选择性地导入部分内容。同时支持 Webpack 4 和 Webpack 5。
功能介绍
用于减小多页面项目中,减少不必要的文件大小。如可以把多语言统一放在一个json文件中,然后根据页面选择性的导入。
json-partial-loader允许你只导入 JSON 文件中的特定部分,而不是整个 JSON 对象。通过在导入语句中使用查询参数 ?key=xxx
或 ?key=xxx,yyy,zzz
,你可以只提取 JSON 中对应键名的值, 多个key对象会深度合并到一个对象。
安装
npm install --save-dev @swordlib/json-partial-loader
yarn add --dev @swordlib/json-partial-loader
pnpm add -D @swordlib/json-partial-loader
Webpack 配置
Webpack 5 配置
const path = require('path');
module.exports = {
mode: 'development',
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.json$/,
resourceQuery: /key=.+/,
type: 'javascript/auto',
use: [
{
loader: '@swordlib/json-partial-loader',
}
]
}
]
},
};
Webpack 4 配置
const path = require('path');
module.exports = {
mode: 'development',
entry: './index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.json$/,
resourceQuery: /key=.+/,
use: [
{
loader: '@swordlib/json-partial-loader',
}
],
type: 'javascript/auto'
}
]
},
};
使用方法
假设你有一个 JSON 文件 data.json
包含以下内容:
{
"user": {
"name": "张三",
"age": 30
},
"product": {
"id": "p001",
"name": "示例产品"
},
"settings": {
"theme": "dark",
"notifications": true
},
"metadata": {
"version": "1.0.0",
"lastUpdated": "2023-01-01"
}
}
你可以这样选择性地导入特定部分:
import userInfo from './data.json?key=user';
import productInfo from './data.json?key=product';
import appSettings from './data.json?key=settings';
import metaData from './data.json?key=metadata';
console.log('用户信息:', userInfo);
console.log('产品信息:', productInfo);
console.log('应用设置:', appSettings);
console.log('元数据:', metaData);
多键导入
你也可以通过逗号分隔的方式一次性导入多个键对应的值。当使用多键导入时,所有指定键对应对象的属性会被深度合并到一个对象中:
import userAndSettings from './data.json?key=user,settings';
console.log('用户和设置:', userAndSettings);
console.log('用户名:', userAndSettings.name);
console.log('主题设置:', userAndSettings.theme);
你还可以导入三个或更多的键:
import allData from './data.json?key=user,product,settings';
深度合并
当导入多个包含嵌套对象的键时,loader 会使用 lodash.merge
进行深度合并:
import mergedUser from './data.json?key=user,additionalUser';
console.log(mergedUser);
工作原理
- 当导入 JSON 文件时,loader 会解析文件内容
- 解析导入语句中的查询参数
?key=xxx
或 ?key=xxx,yyy,zzz
- 从 JSON 对象中提取对应键名的值
- 只导出该键对应的值,而不是整个 JSON 对象
- 当指定多个键时,会使用
lodash.merge
将所有键对应对象的属性深度合并到一个新对象中
优势
- 性能优化:在大型 JSON 文件中,只导入需要的部分可以减少内存使用
- 代码清晰:代码中明确表明只使用 JSON 的特定部分
- 按需加载:在不同组件中可以只导入各自需要的数据
- 灵活组合:可以通过多键导入组合需要的数据
注意事项
- 确保查询参数中的键名存在于 JSON 文件中,否则将得到
undefined
- 当使用多键导入时,如果某个键不存在,该键将被忽略
- 当使用多键导入时,如果不同对象有同名属性,后面的键对应的属性值会覆盖前面的
- 在深度合并时,按照
lodash.merge
的行为,数组会被完全替换而不是合并,这与对象的合并行为不同 - 此 loader 适用于一级键的提取,不支持深层嵌套路径(如
user.profile.name
)
测试
本项目使用 Vitest 进行单元测试。测试覆盖了多种场景:
- 处理没有查询参数的情况
- 根据查询参数提取特定字段
- 处理嵌套的 JSON 对象
- 处理非字符串的输入(已经是对象的情况)
- 处理不存在的键名
- 处理数组类型的 JSON
- 处理包含特殊字符的 JSON
- 通过逗号分隔处理多个键
- 在多键处理中忽略不存在的键
- 处理复杂对象的多键提取
- 处理有空格的多键情况
- 处理空键名列表
运行测试:
npm install
npm test
你也可以通过以下命令运行测试监视模式:
npm run test:watch