From 68c21fe69a20f9c61a2f74dbeeb72dd3d11cf767 Mon Sep 17 00:00:00 2001 From: Ben McCann <322311+benmccann@users.noreply.github.com> Date: Sun, 10 Oct 2021 11:35:53 -0700 Subject: [PATCH] [breaking] do a single bundling with Vite removing esbuild --- .changeset/tidy-pets-tan.md | 9 +++ documentation/docs/80-adapter-api.md | 1 + examples/hn.svelte.dev/svelte.config.js | 4 +- .../adapter-cloudflare-workers/files/entry.js | 5 +- packages/adapter-netlify/files/entry.js | 5 +- packages/adapter-netlify/index.js | 27 +------ packages/adapter-netlify/package.json | 6 +- packages/adapter-node/README.md | 14 ++-- packages/adapter-node/index.js | 74 ++----------------- packages/adapter-node/package.json | 15 ++-- packages/adapter-node/rollup.config.js | 4 +- packages/adapter-node/src/index.js | 16 ++-- packages/adapter-node/src/middlewares.js | 6 +- packages/adapter-node/src/shims.js | 18 +++-- packages/adapter-vercel/files/entry.js | 6 +- packages/adapter-vercel/index.js | 8 +- packages/kit/src/core/build/index.js | 41 ++++++---- packages/kit/src/runtime/app/navigation.js | 18 +++-- packages/kit/types/config.d.ts | 1 + pnpm-lock.yaml | 4 - 20 files changed, 116 insertions(+), 166 deletions(-) create mode 100644 .changeset/tidy-pets-tan.md diff --git a/.changeset/tidy-pets-tan.md b/.changeset/tidy-pets-tan.md new file mode 100644 index 0000000000000..040b4aabf6a35 --- /dev/null +++ b/.changeset/tidy-pets-tan.md @@ -0,0 +1,9 @@ +--- +'@sveltejs/adapter-cloudflare-workers': patch +'@sveltejs/adapter-netlify': patch +'@sveltejs/adapter-node': patch +'@sveltejs/adapter-vercel': patch +'@sveltejs/kit': patch +--- + +[breaking] do a single bundling with Vite removing esbuild diff --git a/documentation/docs/80-adapter-api.md b/documentation/docs/80-adapter-api.md index ef008e7b622a3..15818ae300676 100644 --- a/documentation/docs/80-adapter-api.md +++ b/documentation/docs/80-adapter-api.md @@ -14,6 +14,7 @@ export default function (options) { /** @type {import('@sveltejs/kit').Adapter} */ return { name: 'adapter-package-name', + serverEntryPoint: 'adapter-package-name/entry', async adapt({ utils, config }) { // adapter implementation } diff --git a/examples/hn.svelte.dev/svelte.config.js b/examples/hn.svelte.dev/svelte.config.js index 35c263652b6d3..93fe724215724 100644 --- a/examples/hn.svelte.dev/svelte.config.js +++ b/examples/hn.svelte.dev/svelte.config.js @@ -1,8 +1,8 @@ -import netlify from '@sveltejs/adapter-netlify'; +import adapter from '@sveltejs/adapter-netlify'; export default { kit: { - adapter: netlify(), + adapter: adapter(), target: '#svelte' } }; diff --git a/packages/adapter-cloudflare-workers/files/entry.js b/packages/adapter-cloudflare-workers/files/entry.js index f7a7e397a6201..ed0a77249db2f 100644 --- a/packages/adapter-cloudflare-workers/files/entry.js +++ b/packages/adapter-cloudflare-workers/files/entry.js @@ -1,5 +1,6 @@ -// TODO hardcoding the relative location makes this brittle -import { init, render } from '../output/server/app.js'; +// $server-build doesn't exist until the app is built +// @ts-ignore +import { init, render } from '$server-build'; import { getAssetFromKV, NotFoundError } from '@cloudflare/kv-asset-handler'; init(); diff --git a/packages/adapter-netlify/files/entry.js b/packages/adapter-netlify/files/entry.js index a7fc495392407..b11737d8defa7 100644 --- a/packages/adapter-netlify/files/entry.js +++ b/packages/adapter-netlify/files/entry.js @@ -1,5 +1,6 @@ -// TODO hardcoding the relative location makes this brittle -import { init, render } from '../output/server/app.js'; +// $server-build doesn't exist until the app is built +// @ts-ignore +import { init, render } from '$server-build'; init(); diff --git a/packages/adapter-netlify/index.js b/packages/adapter-netlify/index.js index 2368d0f2d1cd7..4da1007d9847d 100644 --- a/packages/adapter-netlify/index.js +++ b/packages/adapter-netlify/index.js @@ -1,17 +1,13 @@ import { appendFileSync, existsSync, readFileSync, writeFileSync } from 'fs'; import { join, resolve } from 'path'; import { fileURLToPath } from 'url'; -import esbuild from 'esbuild'; import toml from '@iarna/toml'; -/** - * @typedef {import('esbuild').BuildOptions} BuildOptions - */ - /** @type {import('.')} */ -export default function (options) { +export default function () { return { name: '@sveltejs/adapter-netlify', + serverEntryPoint: '@sveltejs/adapter-netlify/entry', async adapt({ utils }) { // "build" is the default publish directory when Netlify detects SvelteKit @@ -24,24 +20,7 @@ export default function (options) { const files = fileURLToPath(new URL('./files', import.meta.url)); utils.log.minor('Generating serverless function...'); - utils.copy(join(files, 'entry.js'), '.svelte-kit/netlify/entry.js'); - - /** @type {BuildOptions} */ - const default_options = { - entryPoints: ['.svelte-kit/netlify/entry.js'], - // Any functions in ".netlify/functions-internal" are bundled in addition to user-defined Netlify functions. - // See https://github.com/netlify/build/pull/3213 for more details - outfile: '.netlify/functions-internal/__render.js', - bundle: true, - inject: [join(files, 'shims.js')], - platform: 'node' - }; - - const build_options = - options && options.esbuild ? await options.esbuild(default_options) : default_options; - - await esbuild.build(build_options); - + utils.copy(files, '.netlify'); writeFileSync(join('.netlify', 'package.json'), JSON.stringify({ type: 'commonjs' })); utils.log.minor('Prerendering static pages...'); diff --git a/packages/adapter-netlify/package.json b/packages/adapter-netlify/package.json index 4532986184f12..b058a1554b072 100644 --- a/packages/adapter-netlify/package.json +++ b/packages/adapter-netlify/package.json @@ -12,6 +12,9 @@ ".": { "import": "./index.js" }, + "./entry": { + "import": "./files/entry.js" + }, "./package.json": "./package.json" }, "main": "index.js", @@ -26,8 +29,7 @@ "check-format": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore" }, "dependencies": { - "@iarna/toml": "^2.2.5", - "esbuild": "^0.13.4" + "@iarna/toml": "^2.2.5" }, "devDependencies": { "@sveltejs/kit": "workspace:*" diff --git a/packages/adapter-node/README.md b/packages/adapter-node/README.md index 6a9a6888cdbe3..89c4e3d974ac9 100644 --- a/packages/adapter-node/README.md +++ b/packages/adapter-node/README.md @@ -15,17 +15,13 @@ export default { adapter: adapter({ // default options are shown out: 'build', - precompress: false, - env: { - host: 'HOST', - port: 'PORT' - } + precompress: false }) } }; ``` -## Options +## Build Options ### entryPoint @@ -39,7 +35,9 @@ The directory to build the server to. It defaults to `build` — i.e. `node buil Enables precompressing using gzip and brotli for assets and prerendered pages. It defaults to `false`. -### env +## Runtime Options + +### Environment variables By default, the server will accept connections on `0.0.0.0` using port 3000. These can be customised with the `PORT` and `HOST` environment variables: @@ -47,7 +45,7 @@ By default, the server will accept connections on `0.0.0.0` using port 3000. The HOST=127.0.0.1 PORT=4000 node build ``` -You can specify different environment variables if necessary using the `env` option. +You can also specify `SOCKET_PATH` if you'd like to use a Unix domain socket or Windows named pipe. ## Middleware diff --git a/packages/adapter-node/index.js b/packages/adapter-node/index.js index 3d2b258fb6a7f..60385341b9424 100644 --- a/packages/adapter-node/index.js +++ b/packages/adapter-node/index.js @@ -1,13 +1,5 @@ -import esbuild from 'esbuild'; -import { - createReadStream, - createWriteStream, - existsSync, - readFileSync, - statSync, - writeFileSync -} from 'fs'; -import { join, resolve } from 'path'; +import { createReadStream, createWriteStream, existsSync, statSync, writeFileSync } from 'fs'; +import { join } from 'path'; import { pipeline } from 'stream'; import glob from 'tiny-glob'; import { fileURLToPath } from 'url'; @@ -16,22 +8,19 @@ import zlib from 'zlib'; const pipe = promisify(pipeline); -/** - * @typedef {import('esbuild').BuildOptions} BuildOptions - */ - /** @type {import('.')} */ export default function ({ - entryPoint = '.svelte-kit/node/index.js', + // TODO: add ability to customize entry point to build/index.js + // entryPoint = '.svelte-kit/node/index.js', out = 'build', precompress, - env: { path: path_env = 'SOCKET_PATH', host: host_env = 'HOST', port: port_env = 'PORT' } = {}, - esbuild: esbuild_config + env: { path: path_env = 'SOCKET_PATH', host: host_env = 'HOST', port: port_env = 'PORT' } = {} } = {}) { return { name: '@sveltejs/adapter-node', + serverEntryPoint: '@sveltejs/adapter-node/entry', - async adapt({ utils, config }) { + async adapt({ utils }) { utils.rimraf(out); utils.log.minor('Copying assets'); @@ -58,54 +47,7 @@ export default function ({ )}] || (!path && 3000);` ); - /** @type {BuildOptions} */ - const defaultOptions = { - entryPoints: ['.svelte-kit/node/middlewares.js'], - outfile: join(out, 'middlewares.js'), - bundle: true, - external: Object.keys(JSON.parse(readFileSync('package.json', 'utf8')).dependencies || {}), - format: 'esm', - platform: 'node', - target: 'node14', - inject: [join(files, 'shims.js')], - define: { - APP_DIR: `"/${config.kit.appDir}/"` - } - }; - const build_options = esbuild_config ? await esbuild_config(defaultOptions) : defaultOptions; - await esbuild.build(build_options); - - utils.log.minor('Building SvelteKit server'); - /** @type {BuildOptions} */ - const default_options_ref_server = { - entryPoints: [entryPoint], - outfile: join(out, 'index.js'), - bundle: true, - format: 'esm', - platform: 'node', - target: 'node14', - // external exclude workaround, see https://github.com/evanw/esbuild/issues/514 - plugins: [ - { - name: 'fix-middlewares-exclude', - setup(build) { - // Match an import of "middlewares.js" and mark it as external - const internal_middlewares_path = resolve('.svelte-kit/node/middlewares.js'); - const build_middlewares_path = resolve(out, 'middlewares.js'); - build.onResolve({ filter: /\/middlewares\.js$/ }, ({ path, resolveDir }) => { - const resolved = resolve(resolveDir, path); - if (resolved === internal_middlewares_path || resolved === build_middlewares_path) { - return { path: './middlewares.js', external: true }; - } - }); - } - } - ] - }; - const build_options_ref_server = esbuild_config - ? await esbuild_config(default_options_ref_server) - : default_options_ref_server; - await esbuild.build(build_options_ref_server); + utils.copy('.svelte-kit/output/server/', 'build/'); utils.log.minor('Prerendering static pages'); await utils.prerender({ diff --git a/packages/adapter-node/package.json b/packages/adapter-node/package.json index 3ae847e861ced..d621b4fc7c8e4 100644 --- a/packages/adapter-node/package.json +++ b/packages/adapter-node/package.json @@ -8,18 +8,20 @@ }, "homepage": "https://kit.svelte.dev", "type": "module", + "main": "index.js", + "types": "index.d.ts", "exports": { ".": { "import": "./index.js" }, + "./entry": { + "import": "./files/index.js" + }, + "./middlewares": { + "import": "./files/middlewares.js" + }, "./package.json": "./package.json" }, - "main": "index.js", - "types": "index.d.ts", - "files": [ - "files", - "index.d.ts" - ], "scripts": { "dev": "rollup -cw", "build": "rollup -c", @@ -30,7 +32,6 @@ "prepublishOnly": "npm run build" }, "dependencies": { - "esbuild": "^0.13.4", "tiny-glob": "^0.2.9" }, "devDependencies": { diff --git a/packages/adapter-node/rollup.config.js b/packages/adapter-node/rollup.config.js index 619756ee6c1eb..42726778c4dfc 100644 --- a/packages/adapter-node/rollup.config.js +++ b/packages/adapter-node/rollup.config.js @@ -11,7 +11,7 @@ export default [ sourcemap: true }, plugins: [nodeResolve(), commonjs(), json()], - external: ['../output/server/app.js', ...require('module').builtinModules] + external: ['$server-build', ...require('module').builtinModules] }, { input: 'src/index.js', @@ -21,7 +21,7 @@ export default [ sourcemap: true }, plugins: [nodeResolve(), commonjs(), json()], - external: ['./middlewares.js', './env.js', ...require('module').builtinModules] + external: ['./middlewares.js', '$server-build', ...require('module').builtinModules] }, { input: 'src/shims.js', diff --git a/packages/adapter-node/src/index.js b/packages/adapter-node/src/index.js index b8e807ea84503..f8af29dc61609 100644 --- a/packages/adapter-node/src/index.js +++ b/packages/adapter-node/src/index.js @@ -1,21 +1,23 @@ -// @ts-ignore -import { path, host, port } from './env.js'; -import { assetsMiddleware, kitMiddleware, prerenderedMiddleware } from './middlewares.js'; +import './shims'; +import { assetsMiddleware, kitMiddleware, prerenderedMiddleware } from './middlewares'; import compression from 'compression'; import polka from 'polka'; +// options +const path = process.env['SOCKET_PATH'] || false; +const host = process.env['HOST'] || '0.0.0.0'; +const port = process.env['PORT'] || (!path && 3000); + const server = polka().use( // https://github.com/lukeed/polka/issues/173 - // @ts-ignore - nothing we can do about so just ignore it + // @ts-expect-error - nothing we can do about so just ignore it compression({ threshold: 0 }), assetsMiddleware, kitMiddleware, prerenderedMiddleware ); -const listenOpts = { path, host, port }; - -server.listen(listenOpts, () => { +server.listen({ path, host, port }, () => { console.log(`Listening on ${path ? path : host + ':' + port}`); }); diff --git a/packages/adapter-node/src/middlewares.js b/packages/adapter-node/src/middlewares.js index ba4ee030244d9..36c155a5baad1 100644 --- a/packages/adapter-node/src/middlewares.js +++ b/packages/adapter-node/src/middlewares.js @@ -1,8 +1,6 @@ -// TODO hardcoding the relative location makes this brittle -// Also, we need most of the logic in another file for testing because -// ../output/server/app.js doesn't exist when we run the tests +// $server-build doesn't exist until the app is built // @ts-ignore -import { init, render } from '../output/server/app.js'; +import { init, render } from '$server-build'; import { create_kit_middleware } from './kit-middleware.js'; import fs from 'fs'; diff --git a/packages/adapter-node/src/shims.js b/packages/adapter-node/src/shims.js index 839b2dd5b108c..56e1459b1f480 100644 --- a/packages/adapter-node/src/shims.js +++ b/packages/adapter-node/src/shims.js @@ -1,9 +1,11 @@ -import { createRequire } from 'module'; -export { fetch, Response, Request, Headers } from '@sveltejs/kit/install-fetch'; +import { fetch, Response, Request, Headers } from '@sveltejs/kit/install-fetch'; -// esbuild automatically renames "require" -// So we still have to use Object.defineProperty here -Object.defineProperty(globalThis, 'require', { - enumerable: true, - value: createRequire(import.meta.url) -}); +if (!globalThis.fetch) { + // @ts-expect-error + globalThis.fetch = fetch; + // @ts-expect-error + globalThis.Response = Response; + // @ts-expect-error + globalThis.Request = Request; + globalThis.Headers = Headers; +} diff --git a/packages/adapter-vercel/files/entry.js b/packages/adapter-vercel/files/entry.js index 35d6e3170a7c7..2d10fdd8b6f73 100644 --- a/packages/adapter-vercel/files/entry.js +++ b/packages/adapter-vercel/files/entry.js @@ -1,8 +1,8 @@ +// $server-build doesn't exist until the app is built +// @ts-ignore +import { init, render } from '$server-build'; import { getRawBody } from '@sveltejs/kit/node'; -// TODO hardcoding the relative location makes this brittle -import { init, render } from '../output/server/app.js'; - init(); export default async (req, res) => { diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js index d5c53689f1435..7f3e01a259ab4 100644 --- a/packages/adapter-vercel/index.js +++ b/packages/adapter-vercel/index.js @@ -23,11 +23,9 @@ export default function (options) { lambda: join(dir, 'functions/node/render') }; - // TODO ideally we'd have something like utils.tmpdir('vercel') - // rather than hardcoding '.svelte-kit/vercel/entry.js', and the - // relative import from that file to output/server/app.js - // would be controlled. at the moment we're exposing - // implementation details that could change + // TODO ideally we'd have something like utils.tmpdir('vercel') rather + // than hardcoding '.svelte-kit/vercel/entry.js'. At the moment we're + // exposing implementation details that could change utils.log.minor('Generating serverless function...'); utils.copy(join(files, 'entry.js'), '.svelte-kit/vercel/entry.js'); diff --git a/packages/kit/src/core/build/index.js b/packages/kit/src/core/build/index.js index 0f02926a66465..dcd3a13f7cf2b 100644 --- a/packages/kit/src/core/build/index.js +++ b/packages/kit/src/core/build/index.js @@ -1,13 +1,11 @@ +import { svelte } from '@sveltejs/vite-plugin-svelte'; import fs from 'fs'; import path from 'path'; - -import { svelte } from '@sveltejs/vite-plugin-svelte'; import glob from 'tiny-glob/sync.js'; import vite from 'vite'; import { rimraf } from '../../utils/filesystem.js'; import { deep_merge } from '../../utils/object.js'; - import { print_config_conflicts } from '../config/index.js'; import { create_app } from '../create_app/index.js'; import create_manifest_data from '../create_manifest_data/index.js'; @@ -26,7 +24,11 @@ const s = (value) => JSON.stringify(value); * @returns {Promise} */ export async function build(config, { cwd = process.cwd(), runtime = '@sveltejs/kit/ssr' } = {}) { - const build_dir = path.resolve(cwd, `${SVELTE_KIT}/build`); + // TODO: build and output are confusing names because they're synonyms + // rename build to intermediate or generated or something clearer + + const raw_build_dir = `${SVELTE_KIT}/build`; + const build_dir = path.resolve(cwd, raw_build_dir); rimraf(build_dir); @@ -47,7 +49,7 @@ export async function build(config, { cwd = process.cwd(), runtime = '@sveltejs/ cwd }), output_dir, - client_entry_file: `${SVELTE_KIT}/build/runtime/internal/start.js`, + client_entry_file: `${raw_build_dir}/runtime/internal/start.js`, service_worker_entry_file: resolve_entry(config.kit.files.serviceWorker) }; @@ -219,12 +221,10 @@ async function build_server( ) { let hooks_file = resolve_entry(config.kit.files.hooks); if (!hooks_file || !fs.existsSync(hooks_file)) { - hooks_file = path.resolve(cwd, `${SVELTE_KIT}/build/hooks.js`); + hooks_file = path.resolve(build_dir, 'hooks.js'); fs.writeFileSync(hooks_file, ''); } - const app_file = `${build_dir}/app.js`; - /** @type {(file: string) => string} */ const app_relative = (file) => { const relative_file = path.relative(build_dir, path.resolve(cwd, file)); @@ -287,6 +287,8 @@ async function build_server( find_deps(client_entry_file, entry_js, entry_css); + const app_file = `${build_dir}/app.js`; + // prettier-ignore fs.writeFileSync( app_file, @@ -441,6 +443,7 @@ async function build_server( build: { target: 'es2020' }, + // TODO: remove after https://github.com/vitejs/vite/pull/5341 is merged and released server: { fs: { strict: true @@ -451,6 +454,17 @@ async function build_server( // don't warn on overriding defaults const [modified_vite_config] = deep_merge(default_config, vite_config); + const adapter = config.kit?.adapter?.serverEntryPoint; + /** + * @type {{ app:string, index?:string }} + */ + const input = { + app: app_file + }; + if (adapter) { + input.index = adapter; + } + /** @type {[any, string[]]} */ const [merged_config, conflicts] = deep_merge(modified_vite_config, { configFile: false, @@ -461,15 +475,12 @@ async function build_server( outDir: `${output_dir}/server`, polyfillDynamicImport: false, rollupOptions: { - input: { - app: app_file - }, + input, output: { format: 'esm', entryFileNames: '[name].js', chunkFileNames: 'chunks/[name]-[hash].js', - assetFileNames: 'assets/[name]-[hash][extname]', - inlineDynamicImports: true + assetFileNames: 'assets/[name]-[hash][extname]' }, preserveEntrySignatures: 'strict' } @@ -482,8 +493,12 @@ async function build_server( } }) ], + define: { + APP_DIR: `"/${config.kit.appDir}/"` + }, resolve: { alias: { + '$server-build': path.resolve(`${build_dir}/app.js`), $app: path.resolve(`${build_dir}/runtime/app`), $lib: config.kit.files.lib } diff --git a/packages/kit/src/runtime/app/navigation.js b/packages/kit/src/runtime/app/navigation.js index 0d32fca7006c3..e1fa5567e730d 100644 --- a/packages/kit/src/runtime/app/navigation.js +++ b/packages/kit/src/runtime/app/navigation.js @@ -1,8 +1,5 @@ -import { router as router_ } from '../client/singletons.js'; import { get_base_uri } from '../client/utils.js'; -const router = /** @type {import('../client/router').Router} */ (router_); - /** * @param {string} name */ @@ -17,11 +14,17 @@ export const invalidate = import.meta.env.SSR ? guard('invalidate') : invalidate export const prefetch = import.meta.env.SSR ? guard('prefetch') : prefetch_; export const prefetchRoutes = import.meta.env.SSR ? guard('prefetchRoutes') : prefetchRoutes_; +async function get_router() { + return /** @type {import('../client/router').Router} */ ( + (await import('../client/singletons.js')).router + ); +} + /** * @type {import('$app/navigation').goto} */ async function goto_(href, opts) { - return router.goto(href, opts, []); + return (await get_router()).goto(href, opts, []); } /** @@ -29,20 +32,21 @@ async function goto_(href, opts) { */ async function invalidate_(resource) { const { href } = new URL(resource, location.href); - return router.renderer.invalidate(href); + return (await get_router()).renderer.invalidate(href); } /** * @type {import('$app/navigation').prefetch} */ -function prefetch_(href) { - return router.prefetch(new URL(href, get_base_uri(document))); +async function prefetch_(href) { + return (await get_router()).prefetch(new URL(href, get_base_uri(document))); } /** * @type {import('$app/navigation').prefetchRoutes} */ async function prefetchRoutes_(pathnames) { + const router = await get_router(); const matching = pathnames ? router.routes.filter((route) => pathnames.some((pathname) => route[0].test(pathname))) : router.routes; diff --git a/packages/kit/types/config.d.ts b/packages/kit/types/config.d.ts index 5d2214d0eacb7..385d2e8d61ffb 100644 --- a/packages/kit/types/config.d.ts +++ b/packages/kit/types/config.d.ts @@ -32,6 +32,7 @@ export interface AdapterUtils { export interface Adapter { name: string; + serverEntryPoint?: string; adapt(context: { utils: AdapterUtils; config: ValidatedConfig }): Promise; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 22f443b3a1c14..a6a5a0d42e0a1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -81,10 +81,8 @@ importers: specifiers: '@iarna/toml': ^2.2.5 '@sveltejs/kit': workspace:* - esbuild: ^0.13.4 dependencies: '@iarna/toml': 2.2.5 - esbuild: 0.13.4 devDependencies: '@sveltejs/kit': link:../kit @@ -95,7 +93,6 @@ importers: '@types/compression': ^1.7.2 c8: ^7.10.0 compression: ^1.7.4 - esbuild: ^0.13.4 node-fetch: ^3.0.0 polka: ^1.0.0-next.22 rollup: ^2.58.0 @@ -103,7 +100,6 @@ importers: tiny-glob: ^0.2.9 uvu: ^0.5.2 dependencies: - esbuild: 0.13.4 tiny-glob: 0.2.9 devDependencies: '@rollup/plugin-json': 4.1.0_rollup@2.58.0