Генерация лицензий из вашего package.json
Создать JSON-файл из ваших зависимостей, перечисленных в файле пакета, действительно просто. Я использую библиотеку под названием license-report, которая сводит эту задачу к одному вызову команды. Мне просто нужно установить пакет в качестве зависимости от разработки для моего проекта и добавить следующий NPM-скрипт.
{
"dep:gen": "license-report --only=prod --output=json > licenses.json"
}
С каждой сборкой Next.js
Поскольку это повторяющаяся задача, которую необходимо выполнять перед каждым развертыванием, чтобы обеспечить текущий результат, я просто добавил ее в команду сборки NPM. Эта команда также используется Next.js, что означает, что всякий раз, когда вы развертываете новую версию (и, следовательно, создаете новую сборку), лицензии из ваших зависимостей генерируются до фактической сборки.
{
"build": "npm run dep:gen && npx next build",
}
Практическая реализация
Наконец, я просто использую json на своей странице Next.js и передаю его как свойство в свое представление. Обратите внимание, что сама страница полностью статична. Следующий пример кода используется точно так же в этом прогрессивном веб-приложении. Они доступны на странице лицензии.
import React from "react";
import { NpmDependency } from "../../models/license/model.license";
import RiExternalLink from "remixicon-react/ExternalLinkLineIcon";
type Props = {
licenses: NpmDependency[];
};
export function Licenses(props: Props) {
const { licenses } = props;
return (
<>
<div className="flex flex-col items-center mb-10 space-y-2 mt-28">
<h1 className="text-5xl">Licenses</h1>
<h2 className="text-xl">All licenses used for flaming.codes</h2>
</div>
<div className="grid max-w-3xl grid-cols-12 gap-10 mx-auto">
{licenses.map((l) => (
<a
key={l.link}
className="flex-col space-y-1 overflow-hidden col-span-full group"
href={l.link.replace("git+", "").replace("ssh://", "")}
target="_blank"
rel="noopener noreferrer"
aria-label={`Open Github repo for ${l.name}`}>
<div className="inline-flex items-end">
<div className="space-x-2 duration-300 ease-in group-hover:translate-x-6 group-hover:opacity-0">
<span className="text-2xl">{l.name}</span>
<span className="opacity-50">{l.installedVersion}</span>
</div>
<div className="absolute mb-1 text-blue-600 duration-300 ease-in -translate-x-4 opacity-0 group-hover:translate-x-0 group-hover:opacity-100">
<RiExternalLink />
</div>
</div>
<div className="text-gray-400">
{[l.licenseType, l.author].filter(Boolean).join(", ")}
</div>
</a>
))}
</div>
</>
);
}