Repository: sveltejs/kit
Pull request #9063 (2023-02-16 04:47:33)

fix: ISR support for `adapter-vercel`
We shipped incremental static regeneration on Vercel last week, but it was broken. Turns out there were a few extra hoops to jump through.

Brief explanation of the changes:

* every route needs a `group`, so that if you invalidate `/foo` you simultaneously invalidate `/foo/__data.json` — this is assigned automatically
* the pathname is passed to the prerender function as the `__pathname` query parameter. `req.url` is reconstructed by `adapter-vercel` before the request is handed off to SvelteKit
* so that we can know if `/foo` or `/foo/__data.json` is being requested, while still allowing `/foo` and `/foo/__data.json` to be invalidate simultaneously, we need to create two Vercel routes for each SvelteKit route with `isr`. To save space, these are symlinks rather than duplicates

### Please don't delete this checklist! Before submitting the PR, please make sure you do the following:
- [x] It's really useful if your PR references an issue where it is discussed ahead of time. In many cases, features are absent for a reason. For large changes, please create an RFC: https://github.com/sveltejs/rfcs
- [x] This message body should clearly illustrate what problems it solves.
- [ ] Ideally, include a test that fails without this PR but passes with it.

### Tests
- [ ] Run the tests with `pnpm test` and lint the project with `pnpm lint` and `pnpm check`

### Changesets
- [x] If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. Changesets that add features should be `minor` and those that fix bugs should be `patch`. Please prefix changeset messages with `feat:`, `fix:`, or `chore:`.



Patch:
diff --git a/.changeset/pretty-kids-camp.md b/.changeset/pretty-kids-camp.md
new file mode 100644
index 000000000..1d8a0f191
--- /dev/null
+++ b/.changeset/pretty-kids-camp.md
@@ -0,0 +1,5 @@
+---
+'@sveltejs/adapter-vercel': patch
+---
+
+fix: get ISR working on Vercel
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index a94d39153..9cde91584 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -9,7 +9,7 @@ body:
     id: bug-description
     attributes:
       label: Describe the bug
-      description: Please [check if bugs related to building are caused by Vite](https://github.com/sveltejs/kit#bug-reporting) and [file there](https://github.com/vitejs/vite/issues) if appropriate. If you intend to submit a PR for this issue, tell us in the description. Thanks!
+      description: Please check if bugs related to building are caused by Vite and [file there](https://github.com/vitejs/vite/issues) if appropriate. If you intend to submit a PR for this issue, tell us in the description. Thanks!
       placeholder: Bug description
     validations:
       required: true
diff --git a/documentation/docs/25-build-and-deploy/40-adapter-node.md b/documentation/docs/25-build-and-deploy/40-adapter-node.md
index ca370579e..f7048bedd 100644
--- a/documentation/docs/25-build-and-deploy/40-adapter-node.md
+++ b/documentation/docs/25-build-and-deploy/40-adapter-node.md
@@ -34,7 +34,7 @@ Development dependencies will be bundled into your app using [Rollup](https://ro
 
 ## Environment variables
 
-In `dev` and `preview`, SvelteKit will read environent variables from your `.env` file (or `.env.local`, or `.env.[mode]`, [as determined by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files).)
+In `dev` and `preview`, SvelteKit will read environment variables from your `.env` file (or `.env.local`, or `.env.[mode]`, [as determined by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files).)
 
 In production, `.env` files are _not_ automatically loaded. To do so, install `dotenv` in your project...
 
@@ -143,7 +143,7 @@ If you need to change the name of the environment variables used to configure th
 
 ### polyfill
 
-Controlls whether your build will load polyfills for missing modules. It defaults to `true`, and should only be disabled when using Node 18.11 or greater.
+Controls whether your build will load polyfills for missing modules. It defaults to `true`, and should only be disabled when using Node 18.11 or greater.
 
 ```js
 envPrefix: 'MY_CUSTOM_';
diff --git a/documentation/docs/25-build-and-deploy/90-adapter-vercel.md b/documentation/docs/25-build-and-deploy/90-adapter-vercel.md
index 6b206385d..9f81325e0 100644
--- a/documentation/docs/25-build-and-deploy/90-adapter-vercel.md
+++ b/documentation/docs/25-build-and-deploy/90-adapter-vercel.md
@@ -88,18 +88,14 @@ export const config = {
 		// Setting the value to `false` means it will never expire.
 		expiration: 60,
 
-		// Option group number of the asset. Assets with the same group number will all be re-validated at the same time.
-		group: 1,
-
 		// Random token that can be provided in the URL to bypass the cached version of the asset, by requesting the asset
 		// with a __prerender_bypass=<token> cookie.
 		//
 		// Making a `GET` or `HEAD` request with `x-prerender-revalidate: <token>` will force the asset to be re-validated.
 		bypassToken: BYPASS_TOKEN,
 
-		// List of query string parameter names that will be cached independently.
-		// If an empty array, query values are not considered for caching.
-		// If `undefined` each unique query value is cached independently
+		// List of valid query parameters. Other parameters (such as utm tracking codes) will be ignored,
+		// ensuring that they do not result in content being regenerated unnecessarily
 		allowQuery: ['search']
 	}
 };
diff --git a/documentation/docs/30-advanced/70-packaging.md b/documentation/docs/30-advanced/70-packaging.md
index 38d17a9c3..f2dc9bf66 100644
--- a/documentation/docs/30-advanced/70-packaging.md
+++ b/documentation/docs/30-advanced/70-packaging.md
@@ -2,33 +2,105 @@
 title: Packaging
 ---
 
-> `svelte-package` is currently experimental. Non-backward compatible changes may occur in any future release.
-
 You can use SvelteKit to build apps as well as component libraries, using the `@sveltejs/package` package (`npm create svelte` has an option to set this up for you).
 
 When you're creating an app, the contents of `src/routes` is the public-facing stuff; [`src/lib`](modules#$lib) contains your app's internal library.
 
-A component library has the exact same structure as a SvelteKit app, except that `src/lib` is the public-facing bit. `src/routes` might be a documentation or demo site that accompanies the library, or it might just be a sandbox you use during development.
+A component library has the exact same structure as a SvelteKit app, except that `src/lib` is the public-facing bit, and your root `package.json` is used to publish the package. `src/routes` might be a documentation or demo site that accompanies the library, or it might just be a sandbox you use during development.
+
+Running the `svelte-package` command from `@sveltejs/package` will take the contents of `src/lib` and generate a `dist` directory (which can be [configured](#options)) containing the following:
+
+- All the files in `src/lib`. Svelte components will be preprocessed, TypeScript files will be transpiled to JavaScript.
+- Type definitions (`d.ts` files) which are generated for Svelte, JavaScript and TypeScript files. You need to install `typescript >= 4.0.0` for this. Type definitions are placed next to their implementation, hand-written `d.ts` files are copied over as is. You can [disable generation](#options), but we strongly recommend against it — people using your library might use TypeScript, for which they require these type definition files.
+
+> `@sveltejs/package` version 1 generated a `package.json`. This is no longer the case and it will now use the `package.json` from your project and validate that it is correct instead. If you're still on version 1, see [this PR](https://github.com/sveltejs/kit/pull/8922) for migration instructions.
+
+## Anatomy of a package.json
+
+Since you're now building a library for public use, the contents of your `package.json` will become more important. Through it, you configure the entry points of your package, which files are published to npm, and which dependencies your library has. Let's go through the most important fields one by one.
+
+### name
+
+This is the name of your package. It will be available for others to install using that name, and visible on `https://npmjs.com/package/<name>`.
+
+```json
+{
+	"name": "your-library"
+}
+```
+
+Read more about it [here](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#name).
+
+### license
+
+Every package should have a license field so people know how they are allowed to use it. A very popular license which is also very permissive in terms of distribution and reuse without warranty is `MIT`.
+
+```json
+{
+	"license": "MIT"
+}
+```
+
+Read more about it [here](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#license). Note that you should also include a `LICENSE` file in your package.
+
+### files
+
+This tells npm which files it will pack up and upload to npm. It should contain your output folder (`dist` by default). Your `package.json` and `README` and `LICENSE` will always be included, so you don't need to specify them.
+
+```json
+{
+	"files": ["dist"]
+}
+```
+
+To exclude unnecessary files (such as unit tests, or modules that are only imported from `src/routes` etc) you can add them to an `.npmignore` file. This will result in smaller packages that are faster to install.
 
-Running the `svelte-package` command from `@sveltejs/package` will take the contents of `src/lib` and generate a `package` directory (which can be [configured](configuration)) containing the following:
+Read more about it [here](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#files).
 
-- All the files in `src/lib`, unless you [configure](configuration) custom `include`/`exclude` options. Svelte components will be preprocessed, TypeScript files will be transpiled to JavaScript.
-- Type definitions (`d.ts` files) which are generated for Svelte, JavaScript and TypeScript files. You need to install `typescript >= 4.0.0` for this. Type definitions are placed next to their implementation, hand-written `d.ts` files are copied over as is. You can [disable generation](configuration), but we strongly recommend against it — people using your library might use TypeScript, for which they require these type definition files.
-- A `package.json` copied from the project root with all fields except `"scripts"`, `"publishConfig.directory"` and `"publishConfig.linkDirectory"`. The `"dependencies"` field is included, which means you should add packages that you only need for your documentation or demo site to `"devDependencies"`. A `"type": "module"` and an `"exports"` field will be added if it's not defined in the original file.
+### exports
 
-The `"exports"` field contains the package's entry points. By default, all files in `src/lib` will be treated as an entry point unless they start with (or live in a directory that starts with) an underscore, but you can [configure](configuration) this behaviour. If you have a `src/lib/index.js` or `src/lib/index.svelte` file, it will be treated as the package root.
+The `"exports"` field contains the package's entry points. If you set up a new library project through `npm create svelte@latest`, it's set to a single export, the package root:
 
-For example, if you had a `src/lib/Foo.svelte` component and a `src/lib/index.js` module that re-exported it, a consumer of your library could do either of the following:
+```json
+{
+	"exports": {
+		".": {
+			"types": "./dist/index.d.ts",
+			"svelte": "./dist/index.js"
+		}
+	}
+}
+```
+
+This tells bundlers and tooling that your package only has one entry point, the root, and everything should be imported through that, like this:
 
 ```js
-// @filename: ambient.d.ts
-declare module 'your-library';
+// @errors: 2307
+import { Something } from 'your-library';
+```
 
-// @filename: index.js
-// ---cut---
-import { Foo } from 'your-library';
+The `types` and `svelte` keys are [export conditions](https://nodejs.org/api/packages.html#conditional-exports). They tell tooling what file to import when they look up the `your-library` import:
+
+- TypeScript sees the `types` condition and looks up the type definition file. If you don't publish type definitions, omit this condition.
+- Svelte-aware tooling sees the `svelte` condition and knows this is a Svelte component library. If you publish a library that does not export any Svelte components and that could also work in non-Svelte projects (for example a Svelte store library), you can replace this condition with `default`.
+
+> Previous versions of `@sveltejs/package` also added a `package.json` export. This is no longer part of the template because all tooling can now deal with a `package.json` not being explicitly exported.
+
+You can adjust `exports` to your liking and provide more entry points. For example, if instead of a `src/lib/index.js` file that re-exported components you wanted to expose a `src/lib/Foo.svelte` component directly, you could create the following export map...
+
+```json
+{
+	"exports": {
+		"./Foo.svelte": {
+			"types": "./dist/Foo.svelte.d.ts",
+			"svelte": "./dist/Foo.svelte"
+		}
+	}
+}
 ```
 
+...and a consumer of your library could import the component like so:
+
 ```js
 // @filename: ambient.d.ts
 declare module 'your-library/Foo.svelte';
@@ -38,26 +110,78 @@ declare module 'your-library/Foo.svelte';
 import Foo from 'your-library/Foo.svelte';
 ```
 
-> You should avoid using [SvelteKit-specific modules](modules) like `$app` in your packages unless you intend for them to only be consumable by other SvelteKit projects. E.g. rather than using `import { browser } from '$app/environment'` you could use [`import.meta.env.SSR`](https://vitejs.dev/guide/env-and-mode.html#env-variables) to make the library available to all Vite-based projects or better yet use [Node conditional exports](https://nodejs.org/api/packages.html#conditional-exports) to make it work for all bundlers. You may also wish to pass in things like the current URL or a navigation action as a prop rather than relying directly on `$app/stores`, `$app/navigation`, etc. Writing your app in this more generic fashion will also make it easier to setup tools for testing, UI demos and so on.
+In general, each key of the exports map is the path the user will have to use to import something from your package, and the value is the path to the file that will be imported or a map of export conditions which in turn contains these file paths.
+
+Read more about `exports` [here](https://nodejs.org/docs/latest-v18.x/api/packages.html#package-entry-points).
+
+### svelte
+
+This is a legacy field that enabled tooling to recognise Svelte component libraries. It's no longer necessary when using the `svelte` [export condition](#anatomy-of-a-package-json-exports), but for backwards compatibility with outdated tooling that doesn't yet know about export conditions it's good to keep it around. It should point towards your root entry point.
+
+```json
+{
+	"svelte": "./dist/index.js"
+}
+```
+
+## Best practices
+
+You should avoid using [SvelteKit-specific modules](modules) like `$app` in your packages unless you intend for them to only be consumable by other SvelteKit projects. E.g. rather than using `import { browser } from '$app/environment'` you could use `import { BROWSER } from 'esm-env'` ([see esm-env docs](https://github.com/benmccann/esm-env)). You may also wish to pass in things like the current URL or a navigation action as a prop rather than relying directly on `$app/stores`, `$app/navigation`, etc. Writing your app in this more generic fashion will also make it easier to setup tools for testing, UI demos and so on.
+
+Ensure that you add [aliases](/docs/configuration#alias) via `svelte.config.js` (not `vite.config.js` or `tsconfig.json`), so that they are processed by `svelte-package`.
+
+You should think carefully about whether or not the changes you make to your package are a bug fix, a new feature, or a breaking change, and update the package version accordingly. Note that if you remove any paths from `exports` or any `export` conditions inside them from your existing library, that should be regarded as a breaking change.
+
+```diff
+{
+	"exports": {
+		".": {
+			"types": "./dist/index.d.ts",
+// changing `svelte` to `default` is a breaking change:
+-			"svelte": "./dist/index.js"
++			"default": "./dist/index.js"
+		},
+// removing this is a breaking change:
+-		"./foo": {
+-			"types": "./dist/foo.d.ts",
+-			"svelte": "./dist/foo.js",
+-			"default": "./dist/foo.js"
+-		},
+// adding this is ok:
++		"./bar": {
++			"types": "./dist/bar.d.ts",
++			"svelte": "./dist/bar.js",
++			"default": "./dist/bar.js"
++		}
+	}
+}
+```
 
 ## Options
 
 `svelte-package` accepts the following options:
 
 - `-w`/`--watch` — watch files in `src/lib` for changes and rebuild the package
+- `-i`/`--input` — the input directory which contains all the files of the package. Defaults to `src/lib`
+- `-o`/`--o` — the output directory where the processed files are written to. You `package.json`'s `exports` should point to files inside there, and the `files` array should include that folder. Defaults to `dist`
+- `-t`/`--types` — whether or not to create type definitions (`d.ts` files). We strongly recommend doing this as it fosters ecosystem library quality. Defaults to `true`
 
 ## Publishing
 
 To publish the generated package:
 
 ```sh
-npm publish ./package
+npm publish
 ```
 
-The `./package` above is referring to the directory name generated, change accordingly if you configure a custom [`package.dir`](configuration).
-
 ## Caveats
 
-All relative file imports need to be fully specified, adhering to Node's ESM algorithm. This means you cannot import the file `src/lib/something/index.js` like `import { something } from './something`, instead you need to import it like this: `import { something } from './something/index.js`. If you are using TypeScript, you need to import `.ts` files the same way, but using a `.js` file ending, _not_ a `.ts` file ending (this isn't under our control, the TypeScript team has made that decision). Setting `"moduleResolution": "NodeNext"` in your `tsconfig.json` or `jsconfig.json` will help you with this.
+All relative file imports need to be fully specified, adhering to Node's ESM algorithm. This means that for a file like `src/lib/something/index.js`, you must include the filename with the extension:
+
+```diff
+-import { something } from './something';
++import { something } from './something/index.js';
+
+If you are using TypeScript, you need to import `.ts` files the same way, but using a `.js` file ending, _not_ a `.ts` file ending. (This is a TypeScript design decision outside our control.) Setting `"moduleResolution": "NodeNext"` in your `tsconfig.json` or `jsconfig.json` will help you with this.
 
-This is a relatively experimental feature and is not yet fully implemented. All files except Svelte files (preprocessed) and TypeScript files (transpiled to JavaScript) are copied across as-is.
+All files except Svelte files (preprocessed) and TypeScript files (transpiled to JavaScript) are copied across as-is.
diff --git a/package.json b/package.json
index 60eb72a2a..8225cfedd 100644
--- a/package.json
+++ b/package.json
@@ -12,7 +12,8 @@
 		"lint": "pnpm -r lint",
 		"format": "pnpm -r format",
 		"precommit": "pnpm format && pnpm lint",
-		"release": "changeset publish"
+		"release": "changeset publish",
+		"start": "cd sites/kit.svelte.dev && npm run dev"
 	},
 	"repository": {
 		"type": "git",
diff --git a/packages/adapter-netlify/CHANGELOG.md b/packages/adapter-netlify/CHANGELOG.md
index 8caf895de..ad81196b3 100644
--- a/packages/adapter-netlify/CHANGELOG.md
+++ b/packages/adapter-netlify/CHANGELOG.md
@@ -1,5 +1,14 @@
 # @sveltejs/adapter-netlify
 
+## 2.0.5
+
+### Patch Changes
+
+- chore: support newest version of undici ([#9005](https://github.com/sveltejs/kit/pull/9005))
+
+- Updated dependencies [[`6cdf54d1`](https://github.com/sveltejs/kit/commit/6cdf54d1f3561348d87f35ddc8330081919eb839)]:
+  - @sveltejs/kit@1.7.1
+
 ## 2.0.4
 
 ### Patch Changes
diff --git a/packages/adapter-netlify/package.json b/packages/adapter-netlify/package.json
index 9be41afc9..ada2fb327 100644
--- a/packages/adapter-netlify/package.json
+++ b/packages/adapter-netlify/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@sveltejs/adapter-netlify",
-	"version": "2.0.4",
+	"version": "2.0.5",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/adapter-netlify/src/headers.js b/packages/adapter-netlify/src/headers.js
index 76770b46a..8fee7ddb3 100644
--- a/packages/adapter-netlify/src/headers.js
+++ b/packages/adapter-netlify/src/headers.js
@@ -17,7 +17,8 @@ export function split_headers(headers) {
 
 	headers.forEach((value, key) => {
 		if (key === 'set-cookie') {
-			m[key] = set_cookie_parser.splitCookiesString(value);
+			if (!m[key]) m[key] = [];
+			m[key].push(...set_cookie_parser.splitCookiesString(value));
 		} else {
 			h[key] = value;
 		}
diff --git a/packages/adapter-static/package.json b/packages/adapter-static/package.json
index 9fd8b1081..71cc78ff1 100644
--- a/packages/adapter-static/package.json
+++ b/packages/adapter-static/package.json
@@ -35,7 +35,7 @@
 		"svelte": "^3.55.1",
 		"typescript": "^4.9.4",
 		"uvu": "^0.5.6",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"peerDependencies": {
 		"@sveltejs/kit": "^1.5.0"
diff --git a/packages/adapter-vercel/files/serverless.js b/packages/adapter-vercel/files/serverless.js
index a9432521e..e2f506c22 100644
--- a/packages/adapter-vercel/files/serverless.js
+++ b/packages/adapter-vercel/files/serverless.js
@@ -11,11 +11,25 @@ await server.init({
 	env: /** @type {Record<string, string>} */ (process.env)
 });
 
+const DATA_SUFFIX = '/__data.json';
+
 /**
  * @param {import('http').IncomingMessage} req
  * @param {import('http').ServerResponse} res
  */
 export default async (req, res) => {
+	if (req.url) {
+		const [path, search] = req.url.split('?');
+
+		const params = new URLSearchParams(search);
+		const pathname = params.get('__pathname');
+
+		if (pathname) {
+			params.delete('__pathname');
+			req.url = `${pathname}${path.endsWith(DATA_SUFFIX) ? DATA_SUFFIX : ''}?${params}`;
+		}
+	}
+
 	/** @type {Request} */
 	let request;
 
diff --git a/packages/adapter-vercel/index.d.ts b/packages/adapter-vercel/index.d.ts
index cdfa2d324..6f95260b4 100644
--- a/packages/adapter-vercel/index.d.ts
+++ b/packages/adapter-vercel/index.d.ts
@@ -36,10 +36,6 @@ export interface ServerlessConfig {
 		 * Expiration time (in seconds) before the cached asset will be re-generated by invoking the Serverless Function. Setting the value to `false` means it will never expire.
 		 */
 		expiration: number | false;
-		/**
-		 * Option group number of the asset. Assets with the same group number will all be re-validated at the same time.
-		 */
-		group?: number;
 		/**
 		 * Random token that can be provided in the URL to bypass the cached version of the asset, by requesting the asset
 		 * with a __prerender_bypass=<token> cookie.
diff --git a/packages/adapter-vercel/index.js b/packages/adapter-vercel/index.js
index 16080fb8d..47d5d648e 100644
--- a/packages/adapter-vercel/index.js
+++ b/packages/adapter-vercel/index.js
@@ -76,22 +76,6 @@ const plugin = function (defaults = {}) {
 					`${dirs.functions}/${name}.func`,
 					config
 				);
-
-				if (config.isr) {
-					write(
-						`${dirs.functions}/${name}.prerender-config.json`,
-						JSON.stringify(
-							{
-								expiration: config.isr.expiration,
-								group: config.isr.group,
-								bypassToken: config.isr.bypassToken,
-								allowQuery: config.isr.allowQuery
-							},
-							null,
-							'\t'
-						)
-					);
-				}
 			}
 
 			/**
@@ -158,6 +142,9 @@ const plugin = function (defaults = {}) {
 			/** @type {Map<string, string>} */
 			const functions = new Map();
 
+			/** @type {Map<import('@sveltejs/kit').RouteDefinition<import('.').Config>, { expiration: number | false, bypassToken: string | undefined, allowQuery: string[], group: number, passQuery: true }>} */
+			const isr_config = new Map();
+
 			// group routes by config
 			for (const route of builder.routes) {
 				if (route.prerender === true) continue;
@@ -175,6 +162,20 @@ const plugin = function (defaults = {}) {
 
 				const config = { runtime, ...defaults, ...route.config };
 
+				if (config.isr) {
+					if (config.isr.allowQuery?.includes('__pathname')) {
+						throw new Error('__pathname is a reserved query parameter for isr.allowQuery');
+					}
+
+					isr_config.set(route, {
+						expiration: config.isr.expiration,
+						bypassToken: config.isr.bypassToken,
+						allowQuery: ['__pathname', ...(config.isr.allowQuery ?? [])],
+						group: isr_config.size + 1,
+						passQuery: true
+					});
+				}
+
 				const hash = hash_config(config);
 
 				// first, check there are no routes with incompatible configs that will be merged
@@ -200,25 +201,28 @@ const plugin = function (defaults = {}) {
 				group.routes.push(route);
 			}
 
+			const singular = groups.size === 1;
+
 			for (const group of groups.values()) {
 				const generate_function =
 					group.config.runtime === 'edge' ? generate_edge_function : generate_serverless_function;
 
 				// generate one function for the group
-				const name = `fn-${group.i}`;
+				const name = singular ? 'fn' : `fn-${group.i}`;
+
 				await generate_function(
 					name,
 					/** @type {any} */ (group.config),
 					/** @type {import('@sveltejs/kit').RouteDefinition<any>[]} */ (group.routes)
 				);
 
-				if (groups.size === 1) {
+				if (singular) {
 					// Special case: One function for all routes
 					static_config.routes.push({ src: '/.*', dest: `/${name}` });
-				} else {
-					for (const route of group.routes) {
-						functions.set(route.pattern.toString(), name);
-					}
+				}
+
+				for (const route of group.routes) {
+					functions.set(route.pattern.toString(), name);
 				}
 			}
 
@@ -238,12 +242,47 @@ const plugin = function (defaults = {}) {
 					src = '^/?';
 				}
 
-				src += '(?:/__data.json)?$';
+				const name = functions.get(pattern) ?? 'fn-0';
+
+				const isr = isr_config.get(route);
+				if (isr) {
+					const isr_name = route.id.slice(1) || '__root__'; // should we check that __root__ isn't a route?
+					const base = `${dirs.functions}/${isr_name}`;
+					builder.mkdirp(base);
+
+					const target = `${dirs.functions}/${name}.func`;
+					const relative = path.relative(path.dirname(base), target);
+
+					// create a symlink to the actual function, but use the
+					// route name so that we can derive the correct URL
+					fs.symlinkSync(relative, `${base}.func`);
+					fs.symlinkSync(`../${relative}`, `${base}/__data.json.func`);
+
+					let i = 1;
+					const pathname = route.segments
+						.map((segment) => {
+							return segment.dynamic ? `$${i++}` : segment.content;
+						})
+						.join('/');
+
+					const json = JSON.stringify(isr, null, '\t');
+
+					write(`${base}.prerender-config.json`, json);
+					write(`${base}/__data.json.prerender-config.json`, json);
+
+					const q = `?__pathname=/${pathname}`;
 
-				const name = functions.get(pattern);
-				if (name) {
-					static_config.routes.push({ src, dest: `/${name}` });
-					functions.delete(pattern);
+					static_config.routes.push({
+						src: src + '$',
+						dest: `${isr_name}${q}`
+					});
+
+					static_config.routes.push({
+						src: src + '/__data.json$',
+						dest: `${isr_name}/__data.json${q}`
+					});
+				} else if (!singular) {
+					static_config.routes.push({ src: src + '(?:/__data.json)?$', dest: `/${name}` });
 				}
 			}
 
@@ -266,11 +305,7 @@ function hash_config(config) {
 		config.external ?? '',
 		config.regions ?? '',
 		config.memory ?? '',
-		config.maxDuration ?? '',
-		config.isr?.expiration ?? '',
-		config.isr?.group ?? '',
-		config.isr?.bypassToken ?? '',
-		config.isr?.allowQuery ?? ''
+		config.maxDuration ?? ''
 	].join('/');
 }
 
@@ -400,22 +435,21 @@ async function create_function_bundle(builder, entry, dir, config) {
 		}
 	}
 
+	const files = Array.from(traced.fileList);
+
 	// find common ancestor directory
 	/** @type {string[]} */
-	let common_parts = [];
+	let common_parts = files[0]?.split(path.sep) ?? [];
 
-	for (const file of traced.fileList) {
-		if (common_parts) {
-			const parts = file.split(path.sep);
+	for (let i = 1; i < files.length; i += 1) {
+		const file = files[i];
+		const parts = file.split(path.sep);
 
-			for (let i = 0; i < common_parts.length; i += 1) {
-				if (parts[i] !== common_parts[i]) {
-					common_parts = common_parts.slice(0, i);
-					break;
-				}
+		for (let j = 0; j < common_parts.length; j += 1) {
+			if (parts[j] !== common_parts[j]) {
+				common_parts = common_parts.slice(0, j);
+				break;
 			}
-		} else {
-			common_parts = path.dirname(file).split(path.sep);
 		}
 	}
 
diff --git a/packages/create-svelte/CHANGELOG.md b/packages/create-svelte/CHANGELOG.md
index dfaffa97f..a6372142c 100644
--- a/packages/create-svelte/CHANGELOG.md
+++ b/packages/create-svelte/CHANGELOG.md
@@ -1,5 +1,17 @@
 # create-svelte
 
+## 3.0.1
+
+### Patch Changes
+
+- fix: update dependency @sveltejs/package to v2.0.0 ([#9087](https://github.com/sveltejs/kit/pull/9087))
+
+## 3.0.0
+
+### Major Changes
+
+- breaking: update library scaffolding for `@sveltejs/package` version 2 ([#8922](https://github.com/sveltejs/kit/pull/8922))
+
 ## 2.3.4
 
 ### Patch Changes
diff --git a/packages/create-svelte/package.json b/packages/create-svelte/package.json
index 6895401ce..0e2559fcc 100644
--- a/packages/create-svelte/package.json
+++ b/packages/create-svelte/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "create-svelte",
-	"version": "2.3.4",
+	"version": "3.0.1",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/create-svelte/templates/default/package.json b/packages/create-svelte/templates/default/package.json
index 14f6fd2c1..4b2342f63 100644
--- a/packages/create-svelte/templates/default/package.json
+++ b/packages/create-svelte/templates/default/package.json
@@ -13,7 +13,7 @@
 		"@sveltejs/kit": "workspace:*",
 		"svelte": "^3.55.1",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.0"
+		"vite": "^4.1.1"
 	},
 	"type": "module",
 	"dependencies": {
diff --git a/packages/create-svelte/templates/skeletonlib/.meta.json b/packages/create-svelte/templates/skeletonlib/.meta.json
index 17f168aca..aa67986ab 100644
--- a/packages/create-svelte/templates/skeletonlib/.meta.json
+++ b/packages/create-svelte/templates/skeletonlib/.meta.json
@@ -1,4 +1,4 @@
 {
-	"title": "Library skeleton project",
+	"title": "Library project",
 	"description": "Barebones scaffolding for your new Svelte library"
 }
diff --git a/packages/create-svelte/templates/skeletonlib/package.template.json b/packages/create-svelte/templates/skeletonlib/package.template.json
index e6ac754c6..0d2d0fcb8 100644
--- a/packages/create-svelte/templates/skeletonlib/package.template.json
+++ b/packages/create-svelte/templates/skeletonlib/package.template.json
@@ -3,17 +3,31 @@
 	"version": "0.0.1",
 	"scripts": {
 		"dev": "vite dev",
-		"build": "svelte-kit sync && svelte-package",
-		"prepublishOnly": "echo 'Did you mean to publish `./package/`, instead of `./`?' && exit 1"
+		"build": "vite build && npm run package",
+		"preview": "vite preview",
+		"package": "svelte-kit sync && svelte-package && publint",
+		"prepublishOnly": "npm run package && publint"
+	},
+	"exports": {
+		".": {
+			"types": "./dist/index.d.ts",
+			"svelte": "./dist/index.js"
+		}
+	},
+	"peerDependencies": {
+		"svelte": "^3.54.0"
 	},
 	"devDependencies": {
 		"@sveltejs/adapter-auto": "^2.0.0",
 		"@sveltejs/kit": "^1.5.0",
-		"@sveltejs/package": "^1.0.0",
+		"@sveltejs/package": "^2.0.0",
+		"publint": "^0.1.9",
 		"svelte": "^3.54.0",
 		"tslib": "^2.4.1",
 		"typescript": "^4.9.3",
 		"vite": "^4.0.0"
 	},
+	"svelte": "./dist/index.js",
+	"types": "./dist/index.d.ts",
 	"type": "module"
 }
diff --git a/packages/kit/CHANGELOG.md b/packages/kit/CHANGELOG.md
index 79282e58c..4e3eefeff 100644
--- a/packages/kit/CHANGELOG.md
+++ b/packages/kit/CHANGELOG.md
@@ -1,5 +1,11 @@
 # @sveltejs/kit
 
+## 1.7.1
+
+### Patch Changes
+
+- fix: deploy server assets. Only works with Vite 4.1+ ([#9073](https://github.com/sveltejs/kit/pull/9073))
+
 ## 1.7.0
 
 ### Minor Changes
diff --git a/packages/kit/package.json b/packages/kit/package.json
index ae056f2fd..4c61aa5f7 100644
--- a/packages/kit/package.json
+++ b/packages/kit/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@sveltejs/kit",
-	"version": "1.7.0",
+	"version": "1.7.1",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
@@ -16,13 +16,13 @@
 		"devalue": "^4.2.3",
 		"esm-env": "^1.0.0",
 		"kleur": "^4.1.5",
-		"magic-string": "^0.27.0",
+		"magic-string": "^0.29.0",
 		"mime": "^3.0.0",
 		"sade": "^1.8.1",
 		"set-cookie-parser": "^2.5.1",
 		"sirv": "^2.0.2",
 		"tiny-glob": "^0.2.9",
-		"undici": "5.18.0"
+		"undici": "5.19.1"
 	},
 	"devDependencies": {
 		"@playwright/test": "^1.29.2",
@@ -38,7 +38,7 @@
 		"svelte-preprocess": "^5.0.0",
 		"typescript": "^4.9.4",
 		"uvu": "^0.5.6",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"peerDependencies": {
 		"svelte": "^3.54.0",
diff --git a/packages/kit/src/core/adapt/builder.js b/packages/kit/src/core/adapt/builder.js
index e28ce02d9..498ac5f4b 100644
--- a/packages/kit/src/core/adapt/builder.js
+++ b/packages/kit/src/core/adapt/builder.js
@@ -1,4 +1,5 @@
 import { existsSync, statSync, createReadStream, createWriteStream } from 'node:fs';
+import { join } from 'node:path/posix';
 import { pipeline } from 'node:stream';
 import { promisify } from 'node:util';
 import zlib from 'node:zlib';
@@ -181,7 +182,12 @@ export function create_builder({
 		},
 
 		writeClient(dest) {
-			return [...copy(`${config.kit.outDir}/output/client`, dest)];
+			const server_assets = copy(
+				`${config.kit.outDir}/output/server/${config.kit.appDir}/immutable/assets`,
+				join(dest, config.kit.appDir, 'immutable/assets')
+			);
+			const client_assets = copy(`${config.kit.outDir}/output/client`, dest);
+			return Array.from(new Set(...server_assets, ...client_assets));
 		},
 
 		// @ts-expect-error
diff --git a/packages/kit/src/exports/vite/index.js b/packages/kit/src/exports/vite/index.js
index d87dba3db..75f70711c 100644
--- a/packages/kit/src/exports/vite/index.js
+++ b/packages/kit/src/exports/vite/index.js
@@ -502,6 +502,7 @@ export function set_assets(path) {
 							},
 							preserveEntrySignatures: 'strict'
 						},
+						ssrEmitAssets: true,
 						target: ssr ? 'node16.14' : undefined,
 						// don't use the default name to avoid collisions with 'static/manifest.json'
 						manifest: 'vite-manifest.json'
diff --git a/packages/migrate/CHANGELOG.md b/packages/migrate/CHANGELOG.md
index e46f48a3c..5828d2eac 100644
--- a/packages/migrate/CHANGELOG.md
+++ b/packages/migrate/CHANGELOG.md
@@ -1,5 +1,17 @@
 # svelte-migrate
 
+## 1.1.1
+
+### Patch Changes
+
+- fix: include utils in migrate's published files ([#9085](https://github.com/sveltejs/kit/pull/9085))
+
+## 1.1.0
+
+### Minor Changes
+
+- feat: add `@sveltejs/package` migration (v1->v2) ([#8922](https://github.com/sveltejs/kit/pull/8922))
+
 ## 1.0.1
 
 ### Patch Changes
diff --git a/packages/migrate/migrations/package/index.js b/packages/migrate/migrations/package/index.js
new file mode 100644
index 000000000..ff193a25c
--- /dev/null
+++ b/packages/migrate/migrations/package/index.js
@@ -0,0 +1,80 @@
+import fs from 'fs';
+import colors from 'kleur';
+import path from 'path';
+import prompts from 'prompts';
+import { pathToFileURL } from 'url';
+import { bail, check_git } from '../../utils.js';
+import { migrate_config } from './migrate_config.js';
+import { migrate_pkg } from './migrate_pkg.js';
+
+export async function migrate() {
+	if (!fs.existsSync('svelte.config.js')) {
+		bail('Please re-run this script in a directory with a svelte.config.js');
+	}
+	if (!fs.existsSync('package.json')) {
+		bail('Please re-run this script in a directory with a package.json');
+	}
+
+	console.log(
+		colors
+			.bold()
+			.yellow(
+				'\nThis will update your svelte.config.js and package.json in the current directory\n'
+			)
+	);
+
+	const use_git = check_git();
+
+	const response = await prompts({
+		type: 'confirm',
+		name: 'value',
+		message: 'Continue?',
+		initial: false
+	});
+
+	if (!response.value) {
+		process.exit(1);
+	}
+
+	const { default: config } = await import(pathToFileURL(path.resolve('svelte.config.js')).href);
+	const has_package_config = !!config.package;
+
+	config.package = {
+		source: path.resolve(config.kit?.files?.lib ?? config.package?.source ?? 'src/lib'),
+		dir: config.package?.dir ?? 'package',
+		exports:
+			config.package?.exports ??
+			((/** @type {string} */ filepath) => !/^_|\/_|\.d\.ts$/.test(filepath)),
+		files: config.package?.files ?? (() => true),
+		emitTypes: config.package?.emitTypes ?? true
+	};
+	config.extensions = config.extensions ?? ['.svelte'];
+
+	migrate_pkg(config);
+
+	if (has_package_config) {
+		migrate_config();
+	}
+
+	console.log(colors.bold().green('✔ Your project has been migrated'));
+
+	console.log('\nRecommended next steps:\n');
+
+	const cyan = colors.bold().cyan;
+
+	const tasks = [
+		use_git && cyan('git commit -m "migration to @sveltejs/package v2"'),
+		`Review the migration guide at https://github.com/sveltejs/kit/pull/8922`,
+		`Read the updated docs at https://kit.svelte.dev/docs/packaging`
+	].filter(Boolean);
+
+	tasks.forEach((task, i) => {
+		console.log(`  ${i + 1}: ${task}`);
+	});
+
+	console.log('');
+
+	if (use_git) {
+		console.log(`Run ${cyan('git diff')} to review changes.\n`);
+	}
+}
diff --git a/packages/migrate/migrations/package/migrate_config.js b/packages/migrate/migrations/package/migrate_config.js
new file mode 100644
index 000000000..63e5df62d
--- /dev/null
+++ b/packages/migrate/migrations/package/migrate_config.js
@@ -0,0 +1,81 @@
+import fs from 'fs';
+import colors from 'kleur';
+import MagicString from 'magic-string';
+import ts from 'typescript';
+
+export function migrate_config() {
+	try {
+		const content = fs.readFileSync('svelte.config.js', 'utf8');
+		fs.writeFileSync('svelte.config.js', remove_package_from_config(content));
+	} catch {
+		console.log(
+			colors
+				.bold()
+				.yellow('Could not remove package config from svelte.config.js, please remove it manually')
+		);
+	}
+}
+
+/**
+ * @param {string} content
+ */
+export function remove_package_from_config(content) {
+	const ast = ts.createSourceFile(
+		'filename.ts',
+		content,
+		ts.ScriptTarget.Latest,
+		true,
+		ts.ScriptKind.TS
+	);
+
+	const code = new MagicString(content);
+
+	for (const statement of ast.statements) {
+		if (ts.isExportAssignment(statement)) {
+			if (ts.isObjectLiteralExpression(statement.expression)) {
+				remove(statement.expression);
+			} else if (ts.isIdentifier(statement.expression)) {
+				for (const statement2 of ast.statements) {
+					if (ts.isVariableStatement(statement2)) {
+						for (const declaration of statement2.declarationList.declarations) {
+							if (
+								ts.isIdentifier(declaration.name) &&
+								declaration.name.text === statement.expression.text &&
+								declaration.initializer &&
+								ts.isObjectLiteralExpression(declaration.initializer)
+							) {
+								remove(declaration.initializer);
+							}
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return code.toString();
+
+	/** @param {ts.ObjectLiteralExpression} expression */
+	function remove(expression) {
+		for (let i = 0; i < expression.properties.length; i++) {
+			const property = expression.properties[i];
+			if (
+				ts.isPropertyAssignment(property) &&
+				ts.isIdentifier(property.name) &&
+				property.name.text === 'package' &&
+				ts.isObjectLiteralExpression(property.initializer)
+			) {
+				if (expression.properties.length === 1) {
+					code.overwrite(expression.getStart(), expression.getEnd(), '{}');
+				} else {
+					const next_property = expression.properties[i + 1];
+					if (next_property) {
+						code.remove(property.getStart(), next_property.getStart());
+					} else {
+						code.remove(property.getStart(), content.lastIndexOf('}', expression.getEnd()));
+					}
+				}
+			}
+		}
+	}
+}
diff --git a/packages/migrate/migrations/package/migrate_config.spec.js b/packages/migrate/migrations/package/migrate_config.spec.js
new file mode 100644
index 000000000..e640d1db1
--- /dev/null
+++ b/packages/migrate/migrations/package/migrate_config.spec.js
@@ -0,0 +1,81 @@
+import { test } from 'uvu';
+import * as assert from 'uvu/assert';
+import { remove_package_from_config } from './migrate_config.js';
+
+test('Removes package config #1', () => {
+	const result = remove_package_from_config(`
+    export default {
+        kit: {
+            files: {
+                lib: 'src/lib'
+            }
+        },
+        package: {
+            dir: 'package',
+            exports: (filepath) => !/^_|\/_|\.d\.ts$/.test(filepath),
+            files: () => true
+        },
+        preprocess: []
+    }`);
+	assert.equal(
+		result,
+		`
+    export default {
+        kit: {
+            files: {
+                lib: 'src/lib'
+            }
+        },
+        preprocess: []
+    }`
+	);
+});
+
+test('Removes package config #2', () => {
+	const result = remove_package_from_config(`
+    export default {
+        package: {
+            dir: 'package',
+            exports: (filepath) => !/^_|\/_|\.d\.ts$/.test(filepath),
+            files: () => true
+        },
+    }`);
+	assert.equal(
+		result,
+		`
+    export default {}`
+	);
+});
+
+test('Removes package config #3', () => {
+	const result = remove_package_from_config(`
+    const config = {
+        package: {
+            dir: 'package',
+            exports: (filepath) => !/^_|\/_|\.d\.ts$/.test(filepath),
+            files: () => true
+        },
+    };
+    export default config;`);
+	assert.equal(
+		result,
+		`
+    const config = {};
+    export default config;`
+	);
+});
+
+test('Leaves config untouched', () => {
+	const content = `
+    export default {
+        kit: {
+            files: {
+                lib: 'src/lib'
+            }
+        },
+    }`;
+	const result = remove_package_from_config(content);
+	assert.equal(result, content);
+});
+
+test.run();
diff --git a/packages/migrate/migrations/package/migrate_pkg.js b/packages/migrate/migrations/package/migrate_pkg.js
new file mode 100644
index 000000000..044bb71dc
--- /dev/null
+++ b/packages/migrate/migrations/package/migrate_pkg.js
@@ -0,0 +1,160 @@
+import fs from 'node:fs';
+import path from 'node:path';
+import colors from 'kleur';
+import { guess_indent, posixify, walk } from '../../utils.js';
+
+/**
+ * @param {any} config
+ */
+export function migrate_pkg(config) {
+	const files = scan(config);
+	const pkg_str = fs.readFileSync('package.json', 'utf8');
+	const pkg = update_pkg_json(config, JSON.parse(pkg_str), files);
+	fs.writeFileSync('package.json', JSON.stringify(pkg, null, guess_indent(pkg_str) ?? '\t'));
+}
+
+/**
+ * @param {any} config
+ */
+function scan(config) {
+	return walk(config.package.source).map((file) => analyze(config, file));
+}
+
+/**
+ * @param {any} config
+ * @param {string} file
+ */
+function analyze(config, file) {
+	const name = posixify(file);
+
+	const svelte_extension = config.extensions.find((/** @type {string} */ ext) =>
+		name.endsWith(ext)
+	);
+
+	const dest = svelte_extension
+		? name.slice(0, -svelte_extension.length) + '.svelte'
+		: name.endsWith('.d.ts')
+		? name
+		: name.endsWith('.ts')
+		? name.slice(0, -3) + '.js'
+		: name;
+
+	return {
+		name,
+		dest,
+		is_included: config.package.files(name),
+		is_exported: config.package.exports(name),
+		is_svelte: !!svelte_extension
+	};
+}
+
+/**
+ * @param {any} config
+ * @param {any} pkg
+ * @param {ReturnType<typeof analyze>[]} files
+ */
+export function update_pkg_json(config, pkg, files) {
+	const out_dir = path.relative('.', config.package.dir);
+
+	// See: https://pnpm.io/package_json#publishconfigdirectory
+	if (pkg.publishConfig?.directory || pkg.linkDirectory?.directory) {
+		console.log(
+			colors.yellow(
+				`Detected "publishConfig.directory" or "linkDirectory.directory" fields in your package.json. ` +
+					`This migration removes them, which may or may not be what you want. Please review closely.`
+			)
+		);
+		delete pkg.publishConfig?.directory;
+		delete pkg.linkDirectory?.directory;
+	}
+
+	for (const key in pkg.scripts || []) {
+		const script = pkg.scripts[key];
+		if (script.includes('svelte-package')) {
+			pkg.scripts[key] = script.replace('svelte-package', `svelte-package -o ${out_dir}`);
+		}
+	}
+
+	pkg.type = 'module';
+	pkg.exports = {
+		'./package.json': './package.json',
+		...pkg.exports
+	};
+
+	pkg.files = pkg.files || [];
+	if (!pkg.files.includes(out_dir)) {
+		pkg.files.push(out_dir);
+	}
+
+	if (pkg.devDependencies?.['@sveltejs/package']) {
+		pkg.devDependencies['@sveltejs/package'] = '^2.0.0';
+	}
+
+	/** @type {Record<string, string>} */
+	const clashes = {};
+
+	for (const file of files) {
+		if (file.is_included && file.is_exported) {
+			const original = `$lib/${file.name}`;
+			const key = `./${file.dest}`.replace(/\/index\.js$|(\/[^/]+)\.js$/, '$1');
+
+			if (clashes[key]) {
+				console.log(
+					colors.yellow(
+						`Duplicate "${key}" export. Closely review your "exports" field in package.json after the migration.`
+					)
+				);
+			}
+
+			if (!pkg.exports[key]) {
+				const has_type = config.package.emitTypes && (file.is_svelte || file.dest.endsWith('.js'));
+				const needs_svelte_condition = file.is_svelte || path.basename(file.dest) === 'index.js';
+				// JSON.stringify will remove the undefined entries
+				pkg.exports[key] = {
+					types: has_type
+						? `./${out_dir}/${
+								file.is_svelte ? `${file.dest}.d.ts` : file.dest.slice(0, -'.js'.length) + '.d.ts'
+						  }`
+						: undefined,
+					svelte: needs_svelte_condition ? `./${out_dir}/${file.dest}` : undefined,
+					default: `./${out_dir}/${file.dest}`
+				};
+
+				if (Object.values(pkg.exports[key]).filter(Boolean).length === 1) {
+					pkg.exports[key] = pkg.exports[key].default;
+				}
+			}
+
+			clashes[key] = original;
+		}
+	}
+
+	if (!pkg.svelte && files.some((file) => file.is_svelte)) {
+		// Several heuristics in Kit/vite-plugin-svelte to tell Vite to mark Svelte packages
+		// rely on the "svelte" property. Vite/Rollup/Webpack plugin can all deal with it.
+		// See https://github.com/sveltejs/kit/issues/1959 for more info and related threads.
+		if (pkg.exports['.']) {
+			const svelte_export =
+				typeof pkg.exports['.'] === 'string'
+					? pkg.exports['.']
+					: pkg.exports['.'].svelte || pkg.exports['.'].import || pkg.exports['.'].default;
+			if (svelte_export) {
+				pkg.svelte = svelte_export;
+			} else {
+				console.log(
+					colors.yellow(
+						'Cannot generate a "svelte" entry point because the "." entry in "exports" is not a string. Please specify a "svelte" entry point yourself\n'
+					)
+				);
+			}
+		} else {
+			console.log(
+				colors.yellow(
+					'Cannot generate a "svelte" entry point because the "." entry in "exports" is missing. Please specify a "svelte" entry point yourself\n'
+				)
+			);
+		}
+	}
+
+	return pkg;
+}
diff --git a/packages/migrate/migrations/package/migrate_pkg.spec.js b/packages/migrate/migrations/package/migrate_pkg.spec.js
new file mode 100644
index 000000000..44fce618f
--- /dev/null
+++ b/packages/migrate/migrations/package/migrate_pkg.spec.js
@@ -0,0 +1,138 @@
+import { test } from 'uvu';
+import * as assert from 'uvu/assert';
+import { update_pkg_json } from './migrate_pkg.js';
+
+test('Updates package.json', () => {
+	const result = update_pkg_json(
+		{ package: { dir: 'package', emitTypes: true } },
+		{
+			name: 'foo',
+			version: '1.0.0',
+			scripts: {
+				packages: 'svelte-package'
+			},
+			exports: {
+				'./ignored': './something.js'
+			}
+		},
+		[
+			{
+				name: 'foo/Bar.svelte',
+				dest: 'foo/Bar.svelte',
+				is_exported: true,
+				is_included: true,
+				is_svelte: true
+			},
+			{
+				name: 'foo/Bar2.svelte',
+				dest: 'foo/Bar2.svelte',
+				is_exported: false,
+				is_included: false,
+				is_svelte: true
+			},
+			{
+				name: 'baz.js',
+				dest: 'baz.js',
+				is_exported: true,
+				is_included: true,
+				is_svelte: false
+			},
+			{
+				name: 'index.js',
+				dest: 'index.js',
+				is_exported: true,
+				is_included: true,
+				is_svelte: false
+			},
+			{
+				name: 'ignored.js',
+				dest: 'ignored.js',
+				is_exported: true,
+				is_included: true,
+				is_svelte: false
+			}
+		]
+	);
+	assert.equal(JSON.parse(JSON.stringify(result)), {
+		name: 'foo',
+		version: '1.0.0',
+		type: 'module',
+		files: ['package'],
+		scripts: {
+			packages: 'svelte-package -o package'
+		},
+		exports: {
+			'./package.json': './package.json',
+			'.': {
+				types: './package/index.d.ts',
+				svelte: './package/index.js',
+				default: './package/index.js'
+			},
+			'./foo/Bar.svelte': {
+				types: './package/foo/Bar.svelte.d.ts',
+				svelte: './package/foo/Bar.svelte',
+				default: './package/foo/Bar.svelte'
+			},
+			'./baz': {
+				types: './package/baz.d.ts',
+				default: './package/baz.js'
+			},
+			'./ignored': './something.js'
+		},
+		svelte: './package/index.js'
+	});
+});
+
+test('Updates package.json #2', () => {
+	const result = update_pkg_json(
+		{ package: { dir: 'dist', emitTypes: false } },
+		{
+			name: 'foo',
+			version: '1.0.0'
+		},
+		[
+			{
+				name: 'foo/Bar.svelte',
+				dest: 'foo/Bar.svelte',
+				is_exported: true,
+				is_included: true,
+				is_svelte: true
+			},
+			{
+				name: 'baz.js',
+				dest: 'baz.js',
+				is_exported: true,
+				is_included: true,
+				is_svelte: false
+			},
+			{
+				name: 'index.js',
+				dest: 'index.js',
+				is_exported: true,
+				is_included: true,
+				is_svelte: false
+			}
+		]
+	);
+	assert.equal(JSON.parse(JSON.stringify(result)), {
+		name: 'foo',
+		version: '1.0.0',
+		type: 'module',
+		files: ['dist'],
+		exports: {
+			'./package.json': './package.json',
+			'.': {
+				svelte: './dist/index.js',
+				default: './dist/index.js'
+			},
+			'./foo/Bar.svelte': {
+				svelte: './dist/foo/Bar.svelte',
+				default: './dist/foo/Bar.svelte'
+			},
+			'./baz': './dist/baz.js'
+		},
+		svelte: './dist/index.js'
+	});
+});
+
+test.run();
diff --git a/packages/migrate/migrations/routes/index.js b/packages/migrate/migrations/routes/index.js
index 14b55a393..a6568e531 100644
--- a/packages/migrate/migrations/routes/index.js
+++ b/packages/migrate/migrations/routes/index.js
@@ -1,4 +1,3 @@
-import { execSync } from 'child_process';
 import fs from 'fs';
 import colors from 'kleur';
 import path from 'path';
@@ -9,7 +8,8 @@ import { migrate_scripts } from './migrate_scripts/index.js';
 import { migrate_page } from './migrate_page_js/index.js';
 import { migrate_page_server } from './migrate_page_server/index.js';
 import { migrate_server } from './migrate_server/index.js';
-import { adjust_imports, bail, move_file, relative, task } from './utils.js';
+import { adjust_imports, task } from './utils.js';
+import { bail, relative, move_file, check_git } from '../../utils.js';
 
 export async function migrate() {
 	if (!fs.existsSync('svelte.config.js')) {
@@ -57,34 +57,7 @@ export async function migrate() {
 
 	console.log(colors.bold().yellow('\nThis will overwrite files in the current directory!\n'));
 
-	let use_git = false;
-
-	let dir = process.cwd();
-	do {
-		if (fs.existsSync(path.join(dir, '.git'))) {
-			use_git = true;
-			break;
-		}
-	} while (dir !== (dir = path.dirname(dir)));
-
-	if (use_git) {
-		try {
-			const status = execSync('git status --porcelain', { stdio: 'pipe' }).toString();
-
-			if (status) {
-				const message =
-					'Your git working directory is dirty — we recommend committing your changes before running this migration.\n';
-				console.log(colors.bold().red(message));
-			}
-		} catch {
-			// would be weird to have a .git folder if git is not installed,
-			// but always expect the unexpected
-			const message =
-				'Could not detect a git installation. If this is unexpected, please raise an issue: https://github.com/sveltejs/kit.\n';
-			console.log(colors.bold().red(message));
-			use_git = false;
-		}
-	}
+	const use_git = check_git();
 
 	const response = await prompts({
 		type: 'confirm',
diff --git a/packages/migrate/migrations/routes/migrate_page_js/index.js b/packages/migrate/migrations/routes/migrate_page_js/index.js
index a4947f475..1a2b30ac8 100644
--- a/packages/migrate/migrations/routes/migrate_page_js/index.js
+++ b/packages/migrate/migrations/routes/migrate_page_js/index.js
@@ -1,7 +1,6 @@
 import ts from 'typescript';
 import {
 	automigration,
-	dedent,
 	error,
 	get_function_node,
 	get_object_nodes,
@@ -15,6 +14,7 @@ import {
 	unwrap
 } from '../utils.js';
 import * as TASKS from '../tasks.js';
+import { dedent } from '../../../utils.js';
 
 const give_up = `${error('Update load function', TASKS.PAGE_LOAD)}\n\n`;
 
diff --git a/packages/migrate/migrations/routes/migrate_page_server/index.js b/packages/migrate/migrations/routes/migrate_page_server/index.js
index c5530f059..8475f14ba 100644
--- a/packages/migrate/migrations/routes/migrate_page_server/index.js
+++ b/packages/migrate/migrations/routes/migrate_page_server/index.js
@@ -1,7 +1,6 @@
 import ts from 'typescript';
 import {
 	automigration,
-	dedent,
 	error,
 	get_function_node,
 	get_object_nodes,
@@ -14,6 +13,7 @@ import {
 	uppercase_migration
 } from '../utils.js';
 import * as TASKS from '../tasks.js';
+import { dedent } from '../../../utils.js';
 
 const give_up = `${error('Update +page.server.js', TASKS.PAGE_ENDPOINT)}\n\n`;
 
diff --git a/packages/migrate/migrations/routes/migrate_scripts/index.js b/packages/migrate/migrations/routes/migrate_scripts/index.js
index 2950dae5d..5ecbbe8cd 100644
--- a/packages/migrate/migrations/routes/migrate_scripts/index.js
+++ b/packages/migrate/migrations/routes/migrate_scripts/index.js
@@ -1,14 +1,7 @@
 import ts from 'typescript';
-import {
-	adjust_imports,
-	guess_indent,
-	comment,
-	error,
-	dedent,
-	parse,
-	except_str
-} from '../utils.js';
+import { adjust_imports, error, parse } from '../utils.js';
 import * as TASKS from '../tasks.js';
+import { comment, dedent, except_str, guess_indent } from '../../../utils.js';
 
 /**
  * @param {string} content
diff --git a/packages/migrate/migrations/routes/migrate_server/index.js b/packages/migrate/migrations/routes/migrate_server/index.js
index 71ab5ab55..af3653db1 100644
--- a/packages/migrate/migrations/routes/migrate_server/index.js
+++ b/packages/migrate/migrations/routes/migrate_server/index.js
@@ -1,13 +1,10 @@
 import ts from 'typescript';
 import {
 	automigration,
-	dedent,
 	uppercase_migration,
 	error,
 	get_function_node,
 	get_object_nodes,
-	guess_indent,
-	indent_at_line,
 	is_new,
 	is_string_like,
 	manual_return_migration,
@@ -16,6 +13,7 @@ import {
 	unwrap
 } from '../utils.js';
 import * as TASKS from '../tasks.js';
+import { dedent, guess_indent, indent_at_line } from '../../../utils.js';
 
 const give_up = `${error('Update +server.js', TASKS.STANDALONE_ENDPOINT)}\n\n`;
 
diff --git a/packages/migrate/migrations/routes/utils.js b/packages/migrate/migrations/routes/utils.js
index 708550113..6bfc40f01 100644
--- a/packages/migrate/migrations/routes/utils.js
+++ b/packages/migrate/migrations/routes/utils.js
@@ -1,20 +1,7 @@
 import fs from 'fs';
-import path from 'path';
-import colors from 'kleur';
 import ts from 'typescript';
 import MagicString from 'magic-string';
-import { execFileSync } from 'child_process';
-
-/** @param {string} message */
-export function bail(message) {
-	console.error(colors.bold().red(message));
-	process.exit(1);
-}
-
-/** @param {string} file */
-export function relative(file) {
-	return path.relative('.', file);
-}
+import { comment, indent_at_line } from '../../utils.js';
 
 /**
  * @param {string} description
@@ -37,31 +24,6 @@ export function error(description, comment_id) {
 	return `throw new Error(${JSON.stringify(task(description, comment_id))});`;
 }
 
-/**
- *
- * @param {string} file
- * @param {string} renamed
- * @param {string} content
- * @param {boolean} use_git
- */
-export function move_file(file, renamed, content, use_git) {
-	if (use_git) {
-		execFileSync('git', ['mv', file, renamed]);
-	} else {
-		fs.unlinkSync(file);
-	}
-
-	fs.writeFileSync(renamed, content);
-}
-
-/**
- * @param {string} contents
- * @param {string} indent
- */
-export function comment(contents, indent) {
-	return contents.replace(new RegExp(`^${indent}`, 'gm'), `${indent}// `);
-}
-
 /** @param {string} content */
 export function adjust_imports(content) {
 	try {
@@ -115,86 +77,6 @@ export function adjust_imports(content) {
 	}
 }
 
-/** @param {string} content */
-export function dedent(content) {
-	const indent = guess_indent(content);
-	if (!indent) return content;
-
-	/** @type {string[]} */
-	const substitutions = [];
-
-	try {
-		const ast = ts.createSourceFile(
-			'filename.ts',
-			content,
-			ts.ScriptTarget.Latest,
-			true,
-			ts.ScriptKind.TS
-		);
-
-		const code = new MagicString(content);
-
-		/** @param {ts.Node} node */
-		function walk(node) {
-			if (ts.isTemplateLiteral(node)) {
-				let pos = node.pos;
-				while (/\s/.test(content[pos])) pos += 1;
-
-				code.overwrite(pos, node.end, `____SUBSTITUTION_${substitutions.length}____`);
-				substitutions.push(node.getText());
-			}
-
-			node.forEachChild(walk);
-		}
-
-		ast.forEachChild(walk);
-
-		return code
-			.toString()
-			.replace(new RegExp(`^${indent}`, 'gm'), '')
-			.replace(/____SUBSTITUTION_(\d+)____/g, (match, index) => substitutions[index]);
-	} catch {
-		// as above — ignore this edge case
-		return content;
-	}
-}
-
-/** @param {string} content */
-export function guess_indent(content) {
-	const lines = content.split('\n');
-
-	const tabbed = lines.filter((line) => /^\t+/.test(line));
-	const spaced = lines.filter((line) => /^ {2,}/.test(line));
-
-	if (tabbed.length === 0 && spaced.length === 0) {
-		return null;
-	}
-
-	// More lines tabbed than spaced? Assume tabs, and
-	// default to tabs in the case of a tie (or nothing
-	// to go on)
-	if (tabbed.length >= spaced.length) {
-		return '\t';
-	}
-
-	// Otherwise, we need to guess the multiple
-	const min = spaced.reduce((previous, current) => {
-		const count = /^ +/.exec(current)?.[0].length ?? 0;
-		return Math.min(count, previous);
-	}, Infinity);
-
-	return ' '.repeat(min);
-}
-
-/**
- * @param {string} content
- * @param {number} offset
- */
-export function indent_at_line(content, offset) {
-	const substr = content.substring(content.lastIndexOf('\n', offset) + 1, offset);
-	return /\s*/.exec(substr)?.[0] ?? '';
-}
-
 /**
  *
  * @param {ts.Node} node
@@ -426,16 +308,6 @@ export function parse(content) {
 	}
 }
 
-/**
- * @param {string} content
- * @param {string} except
- */
-export function except_str(content, except) {
-	const start = content.indexOf(except);
-	const end = start + except.length;
-	return content.substring(0, start) + content.substring(end);
-}
-
 /** @param {string} test_file */
 export function read_samples(test_file) {
 	const markdown = fs.readFileSync(new URL('./samples.md', test_file), 'utf8');
diff --git a/packages/migrate/package.json b/packages/migrate/package.json
index 14db5a567..1e0e06745 100644
--- a/packages/migrate/package.json
+++ b/packages/migrate/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "svelte-migrate",
-	"version": "1.0.1",
+	"version": "1.1.1",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
@@ -17,11 +17,14 @@
 	},
 	"files": [
 		"bin.js",
-		"migrations"
+		"migrations",
+		"utils.js",
+		"!migrations/**/*.spec.js",
+		"!migrations/**/samples.md"
 	],
 	"dependencies": {
 		"kleur": "^4.1.5",
-		"magic-string": "^0.27.0",
+		"magic-string": "^0.29.0",
 		"prompts": "^2.4.2",
 		"tiny-glob": "^0.2.9",
 		"typescript": "^4.9.4"
diff --git a/packages/migrate/tsconfig.json b/packages/migrate/tsconfig.json
index 07a6cc58c..1bd4194a4 100644
--- a/packages/migrate/tsconfig.json
+++ b/packages/migrate/tsconfig.json
@@ -9,5 +9,5 @@
 		"moduleResolution": "node",
 		"allowSyntheticDefaultImports": true
 	},
-	"include": ["./migrations/**/*", "./bin.js"]
+	"include": ["./migrations/**/*", "./utils.js", "./bin.js"]
 }
diff --git a/packages/migrate/utils.js b/packages/migrate/utils.js
new file mode 100644
index 000000000..b7e4c7758
--- /dev/null
+++ b/packages/migrate/utils.js
@@ -0,0 +1,200 @@
+import fs from 'node:fs';
+import path from 'node:path';
+import colors from 'kleur';
+import ts from 'typescript';
+import MagicString from 'magic-string';
+import { execFileSync, execSync } from 'node:child_process';
+
+/** @param {string} message */
+export function bail(message) {
+	console.error(colors.bold().red(message));
+	process.exit(1);
+}
+
+/** @param {string} file */
+export function relative(file) {
+	return path.relative('.', file);
+}
+/**
+ *
+ * @param {string} file
+ * @param {string} renamed
+ * @param {string} content
+ * @param {boolean} use_git
+ */
+export function move_file(file, renamed, content, use_git) {
+	if (use_git) {
+		execFileSync('git', ['mv', file, renamed]);
+	} else {
+		fs.unlinkSync(file);
+	}
+
+	fs.writeFileSync(renamed, content);
+}
+
+/**
+ * @param {string} contents
+ * @param {string} indent
+ */
+export function comment(contents, indent) {
+	return contents.replace(new RegExp(`^${indent}`, 'gm'), `${indent}// `);
+}
+
+/** @param {string} content */
+export function dedent(content) {
+	const indent = guess_indent(content);
+	if (!indent) return content;
+
+	/** @type {string[]} */
+	const substitutions = [];
+
+	try {
+		const ast = ts.createSourceFile(
+			'filename.ts',
+			content,
+			ts.ScriptTarget.Latest,
+			true,
+			ts.ScriptKind.TS
+		);
+
+		const code = new MagicString(content);
+
+		/** @param {ts.Node} node */
+		function walk(node) {
+			if (ts.isTemplateLiteral(node)) {
+				let pos = node.pos;
+				while (/\s/.test(content[pos])) pos += 1;
+
+				code.overwrite(pos, node.end, `____SUBSTITUTION_${substitutions.length}____`);
+				substitutions.push(node.getText());
+			}
+
+			node.forEachChild(walk);
+		}
+
+		ast.forEachChild(walk);
+
+		return code
+			.toString()
+			.replace(new RegExp(`^${indent}`, 'gm'), '')
+			.replace(/____SUBSTITUTION_(\d+)____/g, (match, index) => substitutions[index]);
+	} catch {
+		// as above — ignore this edge case
+		return content;
+	}
+}
+
+/** @param {string} content */
+export function guess_indent(content) {
+	const lines = content.split('\n');
+
+	const tabbed = lines.filter((line) => /^\t+/.test(line));
+	const spaced = lines.filter((line) => /^ {2,}/.test(line));
+
+	if (tabbed.length === 0 && spaced.length === 0) {
+		return null;
+	}
+
+	// More lines tabbed than spaced? Assume tabs, and
+	// default to tabs in the case of a tie (or nothing
+	// to go on)
+	if (tabbed.length >= spaced.length) {
+		return '\t';
+	}
+
+	// Otherwise, we need to guess the multiple
+	const min = spaced.reduce((previous, current) => {
+		const count = /^ +/.exec(current)?.[0].length ?? 0;
+		return Math.min(count, previous);
+	}, Infinity);
+
+	return ' '.repeat(min);
+}
+
+/**
+ * @param {string} content
+ * @param {number} offset
+ */
+export function indent_at_line(content, offset) {
+	const substr = content.substring(content.lastIndexOf('\n', offset) + 1, offset);
+	return /\s*/.exec(substr)?.[0] ?? '';
+}
+
+/**
+ * @param {string} content
+ * @param {string} except
+ */
+export function except_str(content, except) {
+	const start = content.indexOf(except);
+	const end = start + except.length;
+	return content.substring(0, start) + content.substring(end);
+}
+
+/**
+ * @returns {boolean} True if git is installed
+ */
+export function check_git() {
+	let use_git = false;
+
+	let dir = process.cwd();
+	do {
+		if (fs.existsSync(path.join(dir, '.git'))) {
+			use_git = true;
+			break;
+		}
+	} while (dir !== (dir = path.dirname(dir)));
+
+	if (use_git) {
+		try {
+			const status = execSync('git status --porcelain', { stdio: 'pipe' }).toString();
+
+			if (status) {
+				const message =
+					'Your git working directory is dirty — we recommend committing your changes before running this migration.\n';
+				console.log(colors.bold().red(message));
+			}
+		} catch {
+			// would be weird to have a .git folder if git is not installed,
+			// but always expect the unexpected
+			const message =
+				'Could not detect a git installation. If this is unexpected, please raise an issue: https://github.com/sveltejs/kit.\n';
+			console.log(colors.bold().red(message));
+			use_git = false;
+		}
+	}
+
+	return use_git;
+}
+
+/**
+ * Get a list of all files in a directory
+ * @param {string} cwd - the directory to walk
+ * @param {boolean} [dirs] - whether to include directories in the result
+ */
+export function walk(cwd, dirs = false) {
+	/** @type {string[]} */
+	const all_files = [];
+
+	/** @param {string} dir */
+	function walk_dir(dir) {
+		const files = fs.readdirSync(path.join(cwd, dir));
+
+		for (const file of files) {
+			const joined = path.join(dir, file);
+			const stats = fs.statSync(path.join(cwd, joined));
+			if (stats.isDirectory()) {
+				if (dirs) all_files.push(joined);
+				walk_dir(joined);
+			} else {
+				all_files.push(joined);
+			}
+		}
+	}
+
+	return walk_dir(''), all_files;
+}
+
+/** @param {string} str */
+export function posixify(str) {
+	return str.replace(/\\/g, '/');
+}
diff --git a/packages/package/CHANGELOG.md b/packages/package/CHANGELOG.md
index cbde16b90..3da4e35c7 100644
--- a/packages/package/CHANGELOG.md
+++ b/packages/package/CHANGELOG.md
@@ -1,5 +1,17 @@
 # @sveltejs/package
 
+## 2.0.1
+
+### Patch Changes
+
+- fix: print version when running `svelte-package --version` ([#9078](https://github.com/sveltejs/kit/pull/9078))
+
+## 2.0.0
+
+### Major Changes
+
+- breaking: remove `package.json` generation and package options from `svelte.config.js`. New default output directory is `dist`. Read the migration guide at https://github.com/sveltejs/kit/pull/8922 to learn how to update ([#8922](https://github.com/sveltejs/kit/pull/8922))
+
 ## 1.0.2
 
 ### Patch Changes
diff --git a/packages/package/package.json b/packages/package/package.json
index 1e0335b32..d702fe731 100644
--- a/packages/package/package.json
+++ b/packages/package/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "@sveltejs/package",
-	"version": "1.0.2",
+	"version": "2.0.1",
 	"repository": {
 		"type": "git",
 		"url": "https://github.com/sveltejs/kit",
diff --git a/packages/package/src/cli.js b/packages/package/src/cli.js
index bb33f5058..a57c8d065 100644
--- a/packages/package/src/cli.js
+++ b/packages/package/src/cli.js
@@ -1,3 +1,4 @@
+import fs from 'node:fs';
 import colors from 'kleur';
 import sade from 'sade';
 import { load_config } from './config.js';
@@ -14,17 +15,38 @@ function handle_error(error) {
 	process.exit(1);
 }
 
-const prog = sade('svelte-package', true).version('__VERSION__');
+const pkg = JSON.parse(fs.readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
+const prog = sade('svelte-package', true).version(pkg.version);
 
 prog
 	.describe('Create a package')
+	.option('-i, --input', 'Input directory')
+	.option('-o, --output', 'Output directory', 'dist')
+	.option('-t, --types', 'Emit type declarations', true)
 	.option('-w, --watch', 'Rerun when files change', false)
-	.action(async ({ watch }) => {
+	.action(async (args) => {
 		try {
 			const config = await load_config();
+
+			// @ts-expect-error
+			if (config.package) {
+				throw new Error(
+					`config.package is no longer supported. See https://github.com/sveltejs/kit/pull/8922 for more information and how to migrate.`
+				);
+			}
+
 			const packaging = await import('./index.js');
 
-			await (watch ? packaging.watch(config) : packaging.build(config));
+			/** @type {import('./types').Options} */
+			const options = {
+				cwd: process.cwd(),
+				input: args.input ?? config.kit?.files?.lib ?? 'src/lib',
+				output: args.output,
+				types: args.types,
+				config
+			};
+
+			await (args.watch ? packaging.watch(options) : packaging.build(options));
 		} catch (error) {
 			handle_error(/** @type {Error} */ (error));
 		}
diff --git a/packages/package/src/config.js b/packages/package/src/config.js
index b094dee11..a0433d355 100644
--- a/packages/package/src/config.js
+++ b/packages/package/src/config.js
@@ -1,39 +1,27 @@
-import path from 'path';
-import fs from 'fs';
-import url from 'url';
+import path from 'node:path';
+import fs from 'node:fs';
+import url from 'node:url';
 
 /**
  * Loads and validates svelte.config.js
  * @param {{ cwd?: string }} options
- * @returns {Promise<import('./types').ValidatedConfig>}
+ * @returns {Promise<import('./types').Options['config']>}
  */
 export async function load_config({ cwd = process.cwd() } = {}) {
 	const config_file = path.join(cwd, 'svelte.config.js');
 
 	if (!fs.existsSync(config_file)) {
-		return process_config({}, { cwd });
+		return {};
 	}
 
-	const config = await import(`${url.pathToFileURL(config_file).href}?ts=${Date.now()}`);
+	const module = await import(`${url.pathToFileURL(config_file).href}?ts=${Date.now()}`);
+	const config = module.default;
 
-	return process_config(config.default, { cwd });
-}
+	if (config.package) {
+		throw new Error(
+			`config.package is no longer supported. See https://github.com/sveltejs/kit/discussions/8825 for more information.`
+		);
+	}
 
-/**
- * @param {import('types').Config} config
- * @returns {import('./types').ValidatedConfig}
- */
-function process_config(config, { cwd = process.cwd() } = {}) {
-	return {
-		extensions: config.extensions ?? ['.svelte'],
-		kit: config.kit,
-		package: {
-			source: path.resolve(cwd, config.kit?.files?.lib ?? config.package?.source ?? 'src/lib'),
-			dir: config.package?.dir ?? 'package',
-			exports: config.package?.exports ?? ((filepath) => !/^_|\/_|\.d\.ts$/.test(filepath)),
-			files: config.package?.files ?? (() => true),
-			emitTypes: config.package?.emitTypes ?? true
-		},
-		preprocess: config.preprocess
-	};
+	return config;
 }
diff --git a/packages/package/src/index.js b/packages/package/src/index.js
index e7af57df8..fb8690934 100644
--- a/packages/package/src/index.js
+++ b/packages/package/src/index.js
@@ -1,105 +1,68 @@
-import * as fs from 'fs';
-import { dirname, join, relative } from 'path';
+import * as fs from 'node:fs';
+import * as path from 'node:path';
 import colors from 'kleur';
 import chokidar from 'chokidar';
 import { preprocess } from 'svelte/compiler';
 import { copy, mkdirp, rimraf } from './filesystem.js';
-import { analyze, generate_pkg, resolve_lib_alias, scan, strip_lang_tags, write } from './utils.js';
+import { analyze, resolve_aliases, scan, strip_lang_tags, write } from './utils.js';
 import { emit_dts, transpile_ts } from './typescript.js';
+import { create_validator } from './validate.js';
 
-const essential_files = ['README', 'LICENSE', 'CHANGELOG', '.gitignore', '.npmignore'];
+/**
+ * @param {import('./types').Options} options
+ */
+export async function build(options) {
+	const { analyse_code, validate } = create_validator(options);
+	await do_build(options, analyse_code);
+	validate();
+}
 
 /**
- * @param {import('./types').ValidatedConfig} config
- * @param {string} cwd
+ * @param {import('./types').Options} options
+ * @param {(name: string, code: string) => void} analyse_code
  */
-export async function build(config, cwd = process.cwd()) {
-	const { source: lib } = config.package;
-	const { dir } = config.package;
+async function do_build(options, analyse_code) {
+	const { input, output, extensions, alias } = normalize_options(options);
 
-	if (!fs.existsSync(lib)) {
-		throw new Error(`${lib} does not exist`);
+	if (!fs.existsSync(input)) {
+		throw new Error(`${path.relative('.', input)} does not exist`);
 	}
 
-	rimraf(dir);
-	mkdirp(dir);
+	rimraf(output);
+	mkdirp(output);
 
-	const files = scan(config);
+	const files = scan(input, extensions);
 
-	if (config.package.emitTypes) {
-		await emit_dts(config, cwd, files);
+	if (options.types) {
+		await emit_dts(input, output, options.cwd, alias, files);
 	}
 
-	const pkg = generate_pkg(cwd, files);
-
-	if (!pkg.dependencies?.svelte && !pkg.peerDependencies?.svelte) {
-		console.warn(
-			'Svelte libraries should include "svelte" in either "dependencies" or "peerDependencies".'
-		);
-	}
-
-	if (!pkg.svelte && files.some((file) => file.is_svelte)) {
-		// Several heuristics in Kit/vite-plugin-svelte to tell Vite to mark Svelte packages
-		// rely on the "svelte" property. Vite/Rollup/Webpack plugin can all deal with it.
-		// See https://github.com/sveltejs/kit/issues/1959 for more info and related threads.
-		if (pkg.exports['.']) {
-			const svelte_export =
-				typeof pkg.exports['.'] === 'string'
-					? pkg.exports['.']
-					: pkg.exports['.'].import || pkg.exports['.'].default;
-			if (svelte_export) {
-				pkg.svelte = svelte_export;
-			} else {
-				console.warn(
-					'Cannot generate a "svelte" entry point because the "." entry in "exports" is not a string. If you set it by hand, please also set one of the options as a "svelte" entry point\n'
-				);
-			}
-		} else {
-			console.warn(
-				'Cannot generate a "svelte" entry point because the "." entry in "exports" is missing. Please specify one or set a "svelte" entry point yourself\n'
-			);
-		}
-	}
-
-	write(join(dir, 'package.json'), JSON.stringify(pkg, null, 2));
-
 	for (const file of files) {
-		await process_file(config, file);
-	}
-
-	const whitelist = fs.readdirSync(cwd).filter((file) => {
-		const lowercased = file.toLowerCase();
-		return essential_files.some((name) => lowercased.startsWith(name.toLowerCase()));
-	});
-
-	for (const pathname of whitelist) {
-		const full_path = join(cwd, pathname);
-		if (fs.lstatSync(full_path).isDirectory()) continue; // just to be sure
-
-		const package_path = join(dir, pathname);
-		if (!fs.existsSync(package_path)) fs.copyFileSync(full_path, package_path);
+		await process_file(input, output, file, options.config.preprocess, alias, analyse_code);
 	}
 
-	const from = relative(cwd, lib);
-	const to = relative(cwd, dir);
-	console.log(colors.bold().green(`${from} -> ${to}`));
-	console.log(`Successfully built '${pkg.name}' package. To publish it to npm:`);
-	console.log(colors.bold().cyan(`  cd ${to}`));
-	console.log(colors.bold().cyan('  npm publish\n'));
+	console.log(
+		colors
+			.bold()
+			.green(`${path.relative(options.cwd, input)} -> ${path.relative(options.cwd, output)}`)
+	);
 }
 
 /**
- * @param {import('./types').ValidatedConfig} config
+ * @param {import('./types').Options} options
  */
-export async function watch(config, cwd = process.cwd()) {
-	await build(config, cwd);
+export async function watch(options) {
+	const { analyse_code, validate } = create_validator(options);
 
-	const message = `\nWatching ${relative(cwd, config.package.source)} for changes...\n`;
+	await do_build(options, analyse_code);
 
-	console.log(message);
+	validate();
 
-	const { source: lib } = config.package;
-	const { dir } = config.package;
+	const { input, output, extensions, alias } = normalize_options(options);
+
+	const message = `\nWatching ${path.relative(options.cwd, input)} for changes...\n`;
+
+	console.log(message);
 
 	/** @type {Array<{ file: import('./types').File, type: string }>} */
 	const pending = [];
@@ -110,29 +73,22 @@ export async function watch(config, cwd = process.cwd()) {
 	/** @type {NodeJS.Timeout} */
 	let timeout;
 
-	const watcher = chokidar.watch(lib, { ignoreInitial: true });
+	const watcher = chokidar.watch(input, { ignoreInitial: true });
 	const ready = new Promise((resolve) => watcher.on('ready', resolve));
 
-	watcher.on('all', async (type, path) => {
-		const file = analyze(config, relative(lib, path));
-		if (!file.is_included) return;
+	watcher.on('all', async (type, filepath) => {
+		const file = analyze(path.relative(input, filepath), extensions);
 
 		pending.push({ file, type });
 
 		clearTimeout(timeout);
 		timeout = setTimeout(async () => {
-			const files = scan(config);
-
-			let should_update_pkg = false;
+			const files = scan(input, extensions);
 
 			const events = pending.slice();
 			pending.length = 0;
 
 			for (const { file, type } of events) {
-				if ((type === 'unlink' || type === 'add') && file.is_exported) {
-					should_update_pkg = true;
-				}
-
 				if (type === 'unlink') {
 					for (const candidate of [
 						file.name,
@@ -140,13 +96,13 @@ export async function watch(config, cwd = process.cwd()) {
 						`${file.base}.d.mts`,
 						`${file.base}.d.cts`
 					]) {
-						const resolved = join(dir, candidate);
+						const resolved = path.join(output, candidate);
 
 						if (fs.existsSync(resolved)) {
 							fs.unlinkSync(resolved);
 
-							const parent = dirname(resolved);
-							if (parent !== dir && fs.readdirSync(parent).length === 0) {
+							const parent = path.dirname(resolved);
+							if (parent !== output && fs.readdirSync(parent).length === 0) {
 								fs.rmdirSync(parent);
 							}
 						}
@@ -155,19 +111,14 @@ export async function watch(config, cwd = process.cwd()) {
 				}
 
 				if (type === 'add' || type === 'change') {
-					await process_file(config, file);
 					console.log(`Processing ${file.name}`);
+					await process_file(input, output, file, options.config.preprocess, alias, analyse_code);
+					validate();
 				}
 			}
 
-			if (should_update_pkg) {
-				const pkg = generate_pkg(cwd, files);
-				write(join(dir, 'package.json'), JSON.stringify(pkg, null, 2));
-				console.log('Updated package.json');
-			}
-
-			if (config.package.emitTypes) {
-				await emit_dts(config, cwd, scan(config));
+			if (options.types) {
+				await emit_dts(input, output, options.cwd, alias, files);
 				console.log('Updated .d.ts files');
 			}
 
@@ -189,21 +140,44 @@ export async function watch(config, cwd = process.cwd()) {
 }
 
 /**
- * @param {import('./types').ValidatedConfig} config
- * @param {import('./types').File} file
+ * @param {import('./types').Options} options
  */
-async function process_file(config, file) {
-	if (!file.is_included) return;
+function normalize_options(options) {
+	const input = path.resolve(options.cwd, options.input);
+	const output = path.resolve(options.cwd, options.output);
+	const extensions = options.config.extensions ?? ['.svelte'];
+
+	const alias = {
+		$lib: path.resolve(options.cwd, options.config.kit?.files?.lib ?? 'src/lib'),
+		...(options.config.kit?.alias ?? {})
+	};
+
+	return {
+		input,
+		output,
+		extensions,
+		alias
+	};
+}
 
-	const filename = join(config.package.source, file.name);
-	const dest = join(config.package.dir, file.dest);
+/**
+ * @param {string} input
+ * @param {string} output
+ * @param {import('./types').File} file
+ * @param {import('svelte/types/compiler/preprocess').PreprocessorGroup | undefined} preprocessor
+ * @param {Record<string, string>} aliases
+ * @param {(name: string, code: string) => void} analyse_code
+ */
+async function process_file(input, output, file, preprocessor, aliases, analyse_code) {
+	const filename = path.join(input, file.name);
+	const dest = path.join(output, file.dest);
 
-	if (file.is_svelte || file.name.endsWith('.ts')) {
+	if (file.is_svelte || file.name.endsWith('.ts') || file.name.endsWith('.js')) {
 		let contents = fs.readFileSync(filename, 'utf-8');
 
 		if (file.is_svelte) {
-			if (config.preprocess) {
-				const preprocessed = (await preprocess(contents, config.preprocess, { filename })).code;
+			if (preprocessor) {
+				const preprocessed = (await preprocess(contents, preprocessor, { filename })).code;
 				contents = strip_lang_tags(preprocessed);
 			}
 		}
@@ -212,7 +186,8 @@ async function process_file(config, file) {
 			contents = await transpile_ts(filename, contents);
 		}
 
-		contents = resolve_lib_alias(file.name, contents, config);
+		contents = resolve_aliases(input, file.name, contents, aliases);
+		analyse_code(file.name, contents);
 		write(dest, contents);
 	} else {
 		copy(filename, dest);
diff --git a/packages/package/src/types.d.ts b/packages/package/src/types.d.ts
index 2350e43f3..3e481ed2b 100644
--- a/packages/package/src/types.d.ts
+++ b/packages/package/src/types.d.ts
@@ -1,11 +1,26 @@
-import type { PackageConfig } from 'types';
+import { PreprocessorGroup } from 'svelte/types/compiler/preprocess';
+
+export interface Options {
+	cwd: string;
+	input: string;
+	output: string;
+	types: boolean;
+	config: {
+		extensions?: string[];
+		kit?: {
+			alias?: Record<string, string>;
+			files?: {
+				lib?: string;
+			};
+		};
+		preprocess?: PreprocessorGroup;
+	};
+}
 
 export interface File {
 	name: string;
 	dest: string;
 	base: string;
-	is_included: boolean;
-	is_exported: boolean;
 	is_svelte: boolean;
 }
 
@@ -20,7 +35,6 @@ export type RecursiveRequired<T> = {
 export interface ValidatedConfig {
 	extensions: string[];
 	kit?: any;
-	package: RecursiveRequired<PackageConfig>;
 	preprocess?: any;
 }
 
diff --git a/packages/package/src/typescript.js b/packages/package/src/typescript.js
index fa75d51c7..db91a6529 100644
--- a/packages/package/src/typescript.js
+++ b/packages/package/src/typescript.js
@@ -2,7 +2,7 @@ import * as fs from 'fs';
 import * as path from 'path';
 import { createRequire } from 'module';
 import { posixify, mkdirp, rimraf, walk } from './filesystem.js';
-import { resolve_lib_alias, write } from './utils.js';
+import { resolve_aliases, write } from './utils.js';
 import { emitDts } from 'svelte2tsx';
 
 /**
@@ -10,18 +10,20 @@ import { emitDts } from 'svelte2tsx';
  * The files are written to a temporary location and those which should be kept
  * are sanitized ($lib alias resolved) and copied over to the destination folder.
  *
- * @param {import('./types').ValidatedConfig} config
+ * @param {string} input
+ * @param {string} output
  * @param {string} cwd
+ * @param {Record<string, string>} alias
  * @param {import('./types').File[]} files
  */
-export async function emit_dts(config, cwd, files) {
-	const tmp = `${config.package.dir}/__package_types_tmp__`;
+export async function emit_dts(input, output, cwd, alias, files) {
+	const tmp = `${output}/__package_types_tmp__`;
 	rimraf(tmp);
 	mkdirp(tmp);
 
 	const require = createRequire(import.meta.url);
 	await emitDts({
-		libRoot: config.package.source,
+		libRoot: input,
 		svelteShimsPath: require.resolve('svelte2tsx/svelte-shims.d.ts'),
 		declarationDir: path.relative(cwd, tmp)
 	});
@@ -34,12 +36,6 @@ export async function emit_dts(config, cwd, files) {
 		if (file.name.endsWith('.d.ts')) {
 			handwritten.add(file.name);
 		}
-
-		if (!file.is_included) {
-			excluded.add(file.base + '.d.ts');
-			excluded.add(file.base + '.d.mts');
-			excluded.add(file.base + '.d.cts');
-		}
 	}
 
 	// resolve $lib alias (TODO others), copy into package dir
@@ -54,7 +50,7 @@ export async function emit_dts(config, cwd, files) {
 		if (excluded.has(normalized)) continue;
 
 		const source = fs.readFileSync(path.join(tmp, normalized), 'utf8');
-		write(path.join(config.package.dir, normalized), resolve_lib_alias(normalized, source, config));
+		write(path.join(output, normalized), resolve_aliases(input, normalized, source, alias));
 	}
 
 	rimraf(tmp);
diff --git a/packages/package/src/utils.js b/packages/package/src/utils.js
index 001970610..7526c10af 100644
--- a/packages/package/src/utils.js
+++ b/packages/package/src/utils.js
@@ -3,21 +3,15 @@ import * as path from 'path';
 import { posixify, mkdirp, walk } from './filesystem.js';
 
 /**
- * Resolves the `$lib` alias.
+ * Resolves aliases
  *
- * TODO: make this more generic to also handle other aliases the user could have defined via
- * `kit.alias`. Also investigate how to do this in a more robust way (right now regex string
- * replacement is used).
- * For more discussion see https://github.com/sveltejs/kit/pull/2453
- *
- * @param {string} file Relative to the lib root
+ * @param {string} input
+ * @param {string} file Relative to the input
  * @param {string} content
- * @param {import('./types').ValidatedConfig} config
+ * @param {Record<string, string>} aliases
  * @returns {string}
  */
-export function resolve_lib_alias(file, content, config) {
-	const aliases = { $lib: path.resolve(config.package.source), ...(config.kit?.alias ?? {}) };
-
+export function resolve_aliases(input, file, content, aliases) {
 	/**
 	 * @param {string} match
 	 * @param {string} _
@@ -27,7 +21,7 @@ export function resolve_lib_alias(file, content, config) {
 		for (const [alias, value] of Object.entries(aliases)) {
 			if (!import_path.startsWith(alias)) continue;
 
-			const full_path = path.join(config.package.source, file);
+			const full_path = path.join(input, file);
 			const full_import_path = path.join(value, import_path.slice(alias.length));
 			let resolved = posixify(path.relative(path.dirname(full_path), full_import_path));
 			resolved = resolved.startsWith('.') ? resolved : './' + resolved;
@@ -67,22 +61,23 @@ export function write(file, contents) {
 }
 
 /**
- * @param {import('./types').ValidatedConfig} config
+ * @param {string} input
+ * @param {string[]} extensions
  * @returns {import('./types').File[]}
  */
-export function scan(config) {
-	return walk(config.package.source).map((file) => analyze(config, file));
+export function scan(input, extensions) {
+	return walk(input).map((file) => analyze(file, extensions));
 }
 
 /**
- * @param {import('./types').ValidatedConfig} config
  * @param {string} file
+ * @param {string[]} extensions
  * @returns {import('./types').File}
  */
-export function analyze(config, file) {
+export function analyze(file, extensions) {
 	const name = posixify(file);
 
-	const svelte_extension = config.extensions.find((ext) => name.endsWith(ext));
+	const svelte_extension = extensions.find((ext) => name.endsWith(ext));
 
 	const base = svelte_extension ? name : name.slice(0, -path.extname(name).length);
 
@@ -98,54 +93,6 @@ export function analyze(config, file) {
 		name,
 		dest,
 		base,
-		is_included: config.package.files(name),
-		is_exported: config.package.exports(name),
 		is_svelte: !!svelte_extension
 	};
 }
-
-/**
- * @param {string} cwd
- * @param {import('./types').File[]} files
- */
-export function generate_pkg(cwd, files) {
-	const pkg = JSON.parse(fs.readFileSync(path.join(cwd, 'package.json'), 'utf8'));
-
-	// Remove fields that are specific to the original package.json
-	// See: https://pnpm.io/package_json#publishconfigdirectory
-	delete pkg.publishConfig?.directory;
-	delete pkg.linkDirectory?.directory;
-	delete pkg.scripts;
-
-	pkg.type = 'module';
-
-	pkg.exports = {
-		'./package.json': './package.json',
-		...pkg.exports
-	};
-
-	/** @type {Record<string, string>} */
-	const clashes = {};
-
-	for (const file of files) {
-		if (file.is_included && file.is_exported) {
-			const original = `$lib/${file.name}`;
-			const entry = `./${file.dest}`;
-			const key = entry.replace(/\/index\.js$|(\/[^/]+)\.js$/, '$1');
-
-			if (clashes[key]) {
-				throw new Error(
-					`Duplicate "${key}" export. Please remove or rename either ${clashes[key]} or ${original}`
-				);
-			}
-
-			if (!pkg.exports[key]) {
-				pkg.exports[key] = entry;
-			}
-
-			clashes[key] = original;
-		}
-	}
-
-	return pkg;
-}
diff --git a/packages/package/src/validate.js b/packages/package/src/validate.js
new file mode 100644
index 000000000..83fe0c25f
--- /dev/null
+++ b/packages/package/src/validate.js
@@ -0,0 +1,173 @@
+import { existsSync, readFileSync } from 'node:fs';
+import colors from 'kleur';
+
+/**
+ * @param {import("./types").Options} options
+ */
+export function create_validator(options) {
+	/** @type {Set<string>} */
+	const imports = new Set();
+	let uses_import_meta = false;
+	let has_svelte_files = false;
+
+	/**
+	 * Checks a file content for problematic imports and things like `import.meta`
+	 * @param {string} name
+	 * @param {string} content
+	 */
+	function analyse_code(name, content) {
+		has_svelte_files =
+			has_svelte_files ||
+			(options.config.extensions ?? ['.svelte']).some((ext) => name.endsWith(ext));
+		uses_import_meta = uses_import_meta || content.includes('import.meta.env');
+
+		const file_imports = [
+			...content.matchAll(/from\s+('|")([^"';,]+?)\1/g),
+			...content.matchAll(/import\s*\(\s*('|")([^"';,]+?)\1\s*\)/g)
+		];
+		for (const [, , import_path] of file_imports) {
+			if (import_path.startsWith('$app/')) {
+				imports.add(import_path);
+			}
+		}
+	}
+
+	function validate() {
+		/** @type {Record<string, any>} */
+		const pkg = JSON.parse(readFileSync('package.json', 'utf-8'));
+		/** @type {string[]} */
+		const warnings = [];
+
+		if (
+			imports.has('$app/environment') &&
+			[...imports].filter((i) => i.startsWith('$app/')).length === 1
+		) {
+			warnings.push(
+				'Avoid usage of `$app/environment` in your code, if you want to library to work for people not using SvelteKit (only regular Svelte, for example). ' +
+					'Consider using packages like `esm-env` instead which provide cross-bundler-compatible environment variables.'
+			);
+		}
+
+		if (uses_import_meta) {
+			warnings.push(
+				'Avoid usage of `import.meta.env` in your code. It requires a bundler to work. ' +
+					'Consider using packages like `esm-env` instead which provide cross-bundler-compatible environment variables.'
+			);
+		}
+
+		if (
+			!(pkg.dependencies?.['@sveltejs/kit'] || pkg.peerDependencies?.['@sveltejs/kit']) &&
+			([...imports].some((i) => i.startsWith('$app/')) || imports.has('@sveltejs/kit'))
+		) {
+			warnings.push(
+				'You are using SvelteKit-specific imports in your code, but you have not declared a dependency on `@sveltejs/kit` in your `package.json`. ' +
+					'Add it to your `dependencies` or `peerDependencies`.'
+			);
+		}
+
+		if (
+			!(pkg.dependencies?.svelte || pkg.peerDependencies?.svelte) &&
+			(has_svelte_files ||
+				[...imports].some((i) => i.startsWith('svelte/') || imports.has('svelte')))
+		) {
+			warnings.push(
+				'You are using Svelte components or Svelte-specific imports in your code, but you have not declared a dependency on `svelte` in your `package.json`. ' +
+					'Add it to your `dependencies` or `peerDependencies`.'
+			);
+		}
+
+		if (pkg.exports) {
+			const { conditions } = traverse_exports(pkg.exports);
+			if (has_svelte_files && !pkg.svelte && !conditions.has('svelte')) {
+				warnings.push(
+					'You are using Svelte files, but did not declare a `svelte` condition in one of your `exports` in your `package.json`. ' +
+						'Add a `svelte` condition to your `exports` to ensure that your package is recognized as Svelte package by tooling. ' +
+						'See https://kit.svelte.dev/docs/packaging#anatomy-of-a-package-json-exports for more info'
+				);
+			}
+
+			if (pkg.svelte) {
+				const root_export = pkg.exports['.'];
+				if (!root_export) {
+					warnings.push(
+						'You have a `svelte` field in your `package.json`, but no root export in your `exports`. Please align them so that bundlers will resolve consistently to the same file.'
+					);
+				} else {
+					const { exports } = traverse_exports({ '.': root_export });
+					if (![...exports].map(export_to_regex).some((_export) => _export.test(pkg.svelte))) {
+						warnings.push(
+							'The `svelte` field in your `package.json` does not match any export in your root `exports`. Please align them so that bundlers will resolve consistently to the same file.'
+						);
+						Object.keys(pkg.exports).map(export_to_regex);
+					}
+				}
+			}
+		} else {
+			warnings.push(
+				'No `exports` field found in `package.json`, please provide one. ' +
+					'See https://kit.svelte.dev/docs/packaging#anatomy-of-a-package-json-exports for more info'
+			);
+		}
+
+		// Just warnings, not errors, because
+		// - would be annoying in watch mode (would have to restart the server)
+		// - maybe there's a custom post-build script that fixes some of these
+		if (warnings.length) {
+			console.log(
+				colors
+					.bold()
+					.yellow('@sveltejs/package found the following issues while packaging your library:')
+			);
+			for (const warning of warnings) {
+				console.log(colors.yellow(`${warning}\n`));
+			}
+		}
+	}
+
+	return {
+		analyse_code,
+		validate
+	};
+}
+
+/**
+ * @param {Record<string, any>} exports_map
+ * @returns {{ exports: Set<string>; conditions: Set<string> }}
+ */
+function traverse_exports(exports_map) {
+	/** @type {Set<string>} */
+	const exports = new Set();
+	/** @type {Set<string>} */
+	const conditions = new Set();
+
+	/**
+	 * @param {Record<string, any>} exports_map
+	 * @param {boolean} is_first_level
+	 */
+	function traverse(exports_map, is_first_level) {
+		for (const key of Object.keys(exports_map ?? {})) {
+			if (is_first_level) {
+				conditions.add(key);
+			}
+
+			const _export = exports_map[key];
+
+			if (typeof _export === 'string') {
+				exports.add(_export);
+			} else {
+				traverse(_export, false);
+			}
+		}
+	}
+
+	traverse(exports_map, true);
+
+	return { exports, conditions };
+}
+
+/** @param {string} _export */
+function export_to_regex(_export) {
+	// $& means the whole matched string
+	const regex_str = _export.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*');
+	return new RegExp(`^${regex_str}$`);
+}
diff --git a/packages/package/types/index.d.ts b/packages/package/types/index.d.ts
deleted file mode 100644
index 0e1ba39b6..000000000
--- a/packages/package/types/index.d.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import type { CompileOptions } from 'svelte/types/compiler/interfaces'; // TODO bump Svelte version, then export from right path
-
-export interface PackageConfig {
-	/**
-	 * Path to the files that should be packaged.
-	 * If this is used inside SvelteKit, this is read from `kit.files.lib` if unset. Defaults to `src/lib` otherwise.
-	 */
-	source?: string;
-	/**
-	 * Output directory
-	 */
-	dir?: string;
-	/**
-	 * Whether to emit type definition files. Defaults to `true`.
-	 */
-	emitTypes?: boolean;
-	/**
-	 * Function that determines if the given filepath will be included in the `exports` field
-	 * of the `package.json`.
-	 */
-	exports?(filepath: string): boolean;
-	/**
-	 * Function that determines if the given file is part of the output.
-	 */
-	files?(filepath: string): boolean;
-}
-
-export interface Config {
-	compilerOptions?: CompileOptions;
-	extensions?: string[];
-	kit?: any;
-	package?: PackageConfig;
-	preprocess?: any;
-}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6af153d93..52c3b9011 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -151,7 +151,7 @@ importers:
       svelte: ^3.55.1
       typescript: ^4.9.4
       uvu: ^0.5.6
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../kit
       '@types/node': 16.18.6
@@ -159,17 +159,17 @@ importers:
       svelte: 3.55.1
       typescript: 4.9.4
       uvu: 0.5.6
-      vite: 4.0.4_@types+node@16.18.6
+      vite: 4.1.1_@types+node@16.18.6
 
   packages/adapter-static/test/apps/prerendered:
     specifiers:
       '@sveltejs/kit': workspace:^
       svelte: ^3.55.1
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../../../kit
       svelte: 3.55.1
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/adapter-static/test/apps/spa:
     specifiers:
@@ -177,13 +177,13 @@ importers:
       '@sveltejs/kit': workspace:^
       sirv-cli: ^2.0.2
       svelte: ^3.55.1
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/adapter-node': link:../../../../adapter-node
       '@sveltejs/kit': link:../../../../kit
       sirv-cli: 2.0.2
       svelte: 3.55.1
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/adapter-vercel:
     specifiers:
@@ -242,7 +242,7 @@ importers:
       '@sveltejs/kit': workspace:*
       svelte: ^3.55.1
       typescript: ^4.9.4
-      vite: ^4.0.0
+      vite: ^4.1.1
     dependencies:
       '@fontsource/fira-mono': 4.5.10
     devDependencies:
@@ -251,7 +251,7 @@ importers:
       '@sveltejs/kit': link:../../../kit
       svelte: 3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/create-svelte/templates/skeleton:
     specifiers:
@@ -274,7 +274,7 @@ importers:
       devalue: ^4.2.3
       esm-env: ^1.0.0
       kleur: ^4.1.5
-      magic-string: ^0.27.0
+      magic-string: ^0.29.0
       marked: ^4.2.3
       mime: ^3.0.0
       rollup: ^3.7.0
@@ -285,23 +285,23 @@ importers:
       svelte-preprocess: ^5.0.0
       tiny-glob: ^0.2.9
       typescript: ^4.9.4
-      undici: 5.18.0
+      undici: 5.19.1
       uvu: ^0.5.6
-      vite: ^4.0.4
+      vite: ^4.1.1
     dependencies:
-      '@sveltejs/vite-plugin-svelte': 2.0.0_svelte@3.55.1+vite@4.0.4
+      '@sveltejs/vite-plugin-svelte': 2.0.0_svelte@3.55.1+vite@4.1.1
       '@types/cookie': 0.5.1
       cookie: 0.5.0
       devalue: 4.2.3
       esm-env: 1.0.0
       kleur: 4.1.5
-      magic-string: 0.27.0
+      magic-string: 0.29.0
       mime: 3.0.0
       sade: 1.8.1
       set-cookie-parser: 2.5.1
       sirv: 2.0.2
       tiny-glob: 0.2.9
-      undici: 5.18.0
+      undici: 5.19.1
     devDependencies:
       '@playwright/test': 1.29.2
       '@types/connect': 3.4.35
@@ -316,7 +316,7 @@ importers:
       svelte-preprocess: 5.0.0_atrrhq7vg4ekua4nnyrpuardle
       typescript: 4.9.4
       uvu: 0.5.6
-      vite: 4.0.4_@types+node@16.18.6
+      vite: 4.1.1_@types+node@16.18.6
 
   packages/kit/test/apps/amp:
     specifiers:
@@ -327,7 +327,7 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/amp': link:../../../../amp
       '@sveltejs/kit': link:../../..
@@ -336,7 +336,7 @@ importers:
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/apps/basics:
     specifiers:
@@ -346,7 +346,7 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../..
       cross-env: 7.0.3
@@ -354,7 +354,7 @@ importers:
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/apps/dev-only:
     specifiers:
@@ -363,14 +363,14 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../..
       cross-env: 7.0.3
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/apps/options:
     specifiers:
@@ -379,14 +379,14 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../..
       cross-env: 7.0.3
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/apps/options-2:
     specifiers:
@@ -396,7 +396,7 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/adapter-node': link:../../../../adapter-node
       '@sveltejs/kit': link:../../..
@@ -404,7 +404,7 @@ importers:
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/apps/writes:
     specifiers:
@@ -414,7 +414,7 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../..
       cross-env: 7.0.3
@@ -422,7 +422,7 @@ importers:
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/build-errors:
     specifiers:
@@ -437,14 +437,14 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/adapter-auto': link:../../../../../adapter-auto
       '@sveltejs/kit': link:../../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/build-errors/apps/prerenderable-not-prerendered:
     specifiers:
@@ -453,14 +453,14 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/adapter-auto': link:../../../../../adapter-auto
       '@sveltejs/kit': link:../../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/build-errors/apps/private-dynamic-env:
     specifiers:
@@ -468,13 +468,13 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/build-errors/apps/private-dynamic-env-dynamic-import:
     specifiers:
@@ -482,13 +482,13 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/build-errors/apps/private-static-env:
     specifiers:
@@ -497,14 +497,14 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../../..
       cross-env: 7.0.3
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/build-errors/apps/private-static-env-dynamic-import:
     specifiers:
@@ -512,13 +512,13 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/build-errors/apps/server-only-folder:
     specifiers:
@@ -526,13 +526,13 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/build-errors/apps/server-only-folder-dynamic-import:
     specifiers:
@@ -540,13 +540,13 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/build-errors/apps/server-only-module:
     specifiers:
@@ -554,13 +554,13 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/build-errors/apps/server-only-module-dynamic-import:
     specifiers:
@@ -568,13 +568,13 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/build-errors/apps/syntax-error:
     specifiers:
@@ -582,13 +582,13 @@ importers:
       svelte: ^3.55.1
       svelte-check: ^3.0.2
       typescript: ^4.9.4
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/prerendering/basics:
     specifiers:
@@ -597,14 +597,14 @@ importers:
       svelte-check: ^3.0.2
       typescript: ^4.9.4
       uvu: ^0.5.6
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
       uvu: 0.5.6
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/prerendering/options:
     specifiers:
@@ -613,14 +613,14 @@ importers:
       svelte-check: ^3.0.2
       typescript: ^4.9.4
       uvu: ^0.5.6
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
       uvu: 0.5.6
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/prerendering/paths-base:
     specifiers:
@@ -629,14 +629,14 @@ importers:
       svelte-check: ^3.0.2
       typescript: ^4.9.4
       uvu: ^0.5.6
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
       uvu: 0.5.6
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/kit/test/prerendering/ssr-false:
     specifiers:
@@ -645,20 +645,20 @@ importers:
       svelte-check: ^3.0.2
       typescript: ^4.9.4
       uvu: ^0.5.6
-      vite: ^4.0.4
+      vite: ^4.1.1
     devDependencies:
       '@sveltejs/kit': link:../../..
       svelte: 3.55.1
       svelte-check: 3.0.2_svelte@3.55.1
       typescript: 4.9.4
       uvu: 0.5.6
-      vite: 4.0.4
+      vite: 4.1.1
 
   packages/migrate:
     specifiers:
       '@types/prompts': ^2.4.1
       kleur: ^4.1.5
-      magic-string: ^0.27.0
+      magic-string: ^0.29.0
       prettier: ^2.8.0
       prompts: ^2.4.2
       tiny-glob: ^0.2.9
@@ -666,7 +666,7 @@ importers:
       uvu: ^0.5.6
     dependencies:
       kleur: 4.1.5
-      magic-string: 0.27.0
+      magic-string: 0.29.0
       prompts: 2.4.2
       tiny-glob: 0.2.9
       typescript: 4.9.4
@@ -709,7 +709,7 @@ importers:
       d3-geo: ^3.0.1
       d3-geo-projection: ^4.0.0
       flexsearch: ^0.7.31
-      magic-string: ^0.27.0
+      magic-string: ^0.29.0
       marked: ^4.2.3
       prism-svelte: ^0.5.0
       prismjs: ^1.29.0
@@ -719,7 +719,7 @@ importers:
       topojson-client: ^3.1.0
       typescript: ^4.9.4
       uvu: ^0.5.6
-      vite: ^4.0.4
+      vite: ^4.1.1
       vite-imagetools: ^4.0.16
     dependencies:
       d3-geo: 3.0.1
@@ -733,7 +733,7 @@ importers:
       '@types/d3-geo': 3.0.2
       '@types/node': 16.18.6
       flexsearch: 0.7.31
-      magic-string: 0.27.0
+      magic-string: 0.29.0
       marked: 4.2.3
       prism-svelte: 0.5.0
       prismjs: 1.29.0
@@ -742,7 +742,7 @@ importers:
       tiny-glob: 0.2.9
       typescript: 4.9.4
       uvu: 0.5.6
-      vite: 4.0.4_@types+node@16.18.6
+      vite: 4.1.1_@types+node@16.18.6
       vite-imagetools: 4.0.16
 
 packages:
@@ -981,12 +981,29 @@ packages:
     resolution: {integrity: sha512-BNV2wN8V6Zduvo7UzxcdjBbLQ906D2KhS804PDufLgx/sanGJCHVJMOIaLvS/b61JKtot1U7P/l1fjrjZ7/E3A==}
     dev: false
 
+  /@esbuild/android-arm/0.16.17:
+    resolution: {integrity: sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==}
+    engines: {node: '>=12'}
+    cpu: [arm]
+    os: [android]
+    requiresBuild: true
+    optional: true
+
   /@esbuild/android-arm/0.16.3:
     resolution: {integrity: sha512-mueuEoh+s1eRbSJqq9KNBQwI4QhQV6sRXIfTyLXSHGMpyew61rOK4qY21uKbXl1iBoMb0AdL1deWFCQVlN2qHA==}
     engines: {node: '>=12'}
     cpu: [arm]
     os: [android]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/android-arm64/0.16.17:
+    resolution: {integrity: sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [android]
+    requiresBuild: true
     optional: true
 
   /@esbuild/android-arm64/0.16.3:
@@ -995,6 +1012,15 @@ packages:
     cpu: [arm64]
     os: [android]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/android-x64/0.16.17:
+    resolution: {integrity: sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [android]
+    requiresBuild: true
     optional: true
 
   /@esbuild/android-x64/0.16.3:
@@ -1003,6 +1029,15 @@ packages:
     cpu: [x64]
     os: [android]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/darwin-arm64/0.16.17:
+    resolution: {integrity: sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [darwin]
+    requiresBuild: true
     optional: true
 
   /@esbuild/darwin-arm64/0.16.3:
@@ -1011,6 +1046,15 @@ packages:
     cpu: [arm64]
     os: [darwin]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/darwin-x64/0.16.17:
+    resolution: {integrity: sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [darwin]
+    requiresBuild: true
     optional: true
 
   /@esbuild/darwin-x64/0.16.3:
@@ -1019,6 +1063,15 @@ packages:
     cpu: [x64]
     os: [darwin]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/freebsd-arm64/0.16.17:
+    resolution: {integrity: sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [freebsd]
+    requiresBuild: true
     optional: true
 
   /@esbuild/freebsd-arm64/0.16.3:
@@ -1027,6 +1080,15 @@ packages:
     cpu: [arm64]
     os: [freebsd]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/freebsd-x64/0.16.17:
+    resolution: {integrity: sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [freebsd]
+    requiresBuild: true
     optional: true
 
   /@esbuild/freebsd-x64/0.16.3:
@@ -1035,6 +1097,15 @@ packages:
     cpu: [x64]
     os: [freebsd]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/linux-arm/0.16.17:
+    resolution: {integrity: sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==}
+    engines: {node: '>=12'}
+    cpu: [arm]
+    os: [linux]
+    requiresBuild: true
     optional: true
 
   /@esbuild/linux-arm/0.16.3:
@@ -1043,6 +1114,15 @@ packages:
     cpu: [arm]
     os: [linux]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/linux-arm64/0.16.17:
+    resolution: {integrity: sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [linux]
+    requiresBuild: true
     optional: true
 
   /@esbuild/linux-arm64/0.16.3:
@@ -1051,6 +1131,15 @@ packages:
     cpu: [arm64]
     os: [linux]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/linux-ia32/0.16.17:
+    resolution: {integrity: sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==}
+    engines: {node: '>=12'}
+    cpu: [ia32]
+    os: [linux]
+    requiresBuild: true
     optional: true
 
   /@esbuild/linux-ia32/0.16.3:
@@ -1059,6 +1148,15 @@ packages:
     cpu: [ia32]
     os: [linux]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/linux-loong64/0.16.17:
+    resolution: {integrity: sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==}
+    engines: {node: '>=12'}
+    cpu: [loong64]
+    os: [linux]
+    requiresBuild: true
     optional: true
 
   /@esbuild/linux-loong64/0.16.3:
@@ -1067,6 +1165,15 @@ packages:
     cpu: [loong64]
     os: [linux]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/linux-mips64el/0.16.17:
+    resolution: {integrity: sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==}
+    engines: {node: '>=12'}
+    cpu: [mips64el]
+    os: [linux]
+    requiresBuild: true
     optional: true
 
   /@esbuild/linux-mips64el/0.16.3:
@@ -1075,6 +1182,15 @@ packages:
     cpu: [mips64el]
     os: [linux]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/linux-ppc64/0.16.17:
+    resolution: {integrity: sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==}
+    engines: {node: '>=12'}
+    cpu: [ppc64]
+    os: [linux]
+    requiresBuild: true
     optional: true
 
   /@esbuild/linux-ppc64/0.16.3:
@@ -1083,6 +1199,15 @@ packages:
     cpu: [ppc64]
     os: [linux]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/linux-riscv64/0.16.17:
+    resolution: {integrity: sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==}
+    engines: {node: '>=12'}
+    cpu: [riscv64]
+    os: [linux]
+    requiresBuild: true
     optional: true
 
   /@esbuild/linux-riscv64/0.16.3:
@@ -1091,6 +1216,15 @@ packages:
     cpu: [riscv64]
     os: [linux]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/linux-s390x/0.16.17:
+    resolution: {integrity: sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==}
+    engines: {node: '>=12'}
+    cpu: [s390x]
+    os: [linux]
+    requiresBuild: true
     optional: true
 
   /@esbuild/linux-s390x/0.16.3:
@@ -1099,6 +1233,15 @@ packages:
     cpu: [s390x]
     os: [linux]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/linux-x64/0.16.17:
+    resolution: {integrity: sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [linux]
+    requiresBuild: true
     optional: true
 
   /@esbuild/linux-x64/0.16.3:
@@ -1107,6 +1250,15 @@ packages:
     cpu: [x64]
     os: [linux]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/netbsd-x64/0.16.17:
+    resolution: {integrity: sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [netbsd]
+    requiresBuild: true
     optional: true
 
   /@esbuild/netbsd-x64/0.16.3:
@@ -1115,6 +1267,15 @@ packages:
     cpu: [x64]
     os: [netbsd]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/openbsd-x64/0.16.17:
+    resolution: {integrity: sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [openbsd]
+    requiresBuild: true
     optional: true
 
   /@esbuild/openbsd-x64/0.16.3:
@@ -1123,6 +1284,15 @@ packages:
     cpu: [x64]
     os: [openbsd]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/sunos-x64/0.16.17:
+    resolution: {integrity: sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [sunos]
+    requiresBuild: true
     optional: true
 
   /@esbuild/sunos-x64/0.16.3:
@@ -1131,6 +1301,15 @@ packages:
     cpu: [x64]
     os: [sunos]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/win32-arm64/0.16.17:
+    resolution: {integrity: sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==}
+    engines: {node: '>=12'}
+    cpu: [arm64]
+    os: [win32]
+    requiresBuild: true
     optional: true
 
   /@esbuild/win32-arm64/0.16.3:
@@ -1139,6 +1318,15 @@ packages:
     cpu: [arm64]
     os: [win32]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/win32-ia32/0.16.17:
+    resolution: {integrity: sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==}
+    engines: {node: '>=12'}
+    cpu: [ia32]
+    os: [win32]
+    requiresBuild: true
     optional: true
 
   /@esbuild/win32-ia32/0.16.3:
@@ -1147,6 +1335,15 @@ packages:
     cpu: [ia32]
     os: [win32]
     requiresBuild: true
+    dev: false
+    optional: true
+
+  /@esbuild/win32-x64/0.16.17:
+    resolution: {integrity: sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==}
+    engines: {node: '>=12'}
+    cpu: [x64]
+    os: [win32]
+    requiresBuild: true
     optional: true
 
   /@esbuild/win32-x64/0.16.3:
@@ -1155,6 +1352,7 @@ packages:
     cpu: [x64]
     os: [win32]
     requiresBuild: true
+    dev: false
     optional: true
 
   /@eslint-community/eslint-utils/4.1.2_eslint@8.33.0:
@@ -1392,7 +1590,7 @@ packages:
     resolution: {integrity: sha512-Vv9Efzax+NMRZUfZ9TdUqQYicj2Z3kynLkUUdGPfahjlFEwQ3EGyj1vVCg5jxyqvNUgOsVVUb35nXI5CPsmCfA==}
     dev: true
 
-  /@sveltejs/vite-plugin-svelte/2.0.0_svelte@3.55.1+vite@4.0.4:
+  /@sveltejs/vite-plugin-svelte/2.0.0_svelte@3.55.1+vite@4.1.1:
     resolution: {integrity: sha512-oUFrYQarRv4fppmxdrv00qw3wX8Ycdj0uv33MfpRZyR8K67dyxiOcHnqkB0zSy5sDJA8RC/2aNtYhXJ8NINVHQ==}
     engines: {node: ^14.18.0 || >= 16}
     peerDependencies:
@@ -1405,8 +1603,8 @@ packages:
       magic-string: 0.27.0
       svelte: 3.55.1
       svelte-hmr: 0.15.1_svelte@3.55.1
-      vite: 4.0.4_@types+node@16.18.6
-      vitefu: 0.2.3_vite@4.0.4
+      vite: 4.1.1_@types+node@16.18.6
+      vitefu: 0.2.3_vite@4.1.1
     transitivePeerDependencies:
       - supports-color
     dev: false
@@ -2295,6 +2493,35 @@ packages:
     resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==}
     dev: true
 
+  /esbuild/0.16.17:
+    resolution: {integrity: sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==}
+    engines: {node: '>=12'}
+    hasBin: true
+    requiresBuild: true
+    optionalDependencies:
+      '@esbuild/android-arm': 0.16.17
+      '@esbuild/android-arm64': 0.16.17
+      '@esbuild/android-x64': 0.16.17
+      '@esbuild/darwin-arm64': 0.16.17
+      '@esbuild/darwin-x64': 0.16.17
+      '@esbuild/freebsd-arm64': 0.16.17
+      '@esbuild/freebsd-x64': 0.16.17
+      '@esbuild/linux-arm': 0.16.17
+      '@esbuild/linux-arm64': 0.16.17
+      '@esbuild/linux-ia32': 0.16.17
+      '@esbuild/linux-loong64': 0.16.17
+      '@esbuild/linux-mips64el': 0.16.17
+      '@esbuild/linux-ppc64': 0.16.17
+      '@esbuild/linux-riscv64': 0.16.17
+      '@esbuild/linux-s390x': 0.16.17
+      '@esbuild/linux-x64': 0.16.17
+      '@esbuild/netbsd-x64': 0.16.17
+      '@esbuild/openbsd-x64': 0.16.17
+      '@esbuild/sunos-x64': 0.16.17
+      '@esbuild/win32-arm64': 0.16.17
+      '@esbuild/win32-ia32': 0.16.17
+      '@esbuild/win32-x64': 0.16.17
+
   /esbuild/0.16.3:
     resolution: {integrity: sha512-71f7EjPWTiSguen8X/kxEpkAS7BFHwtQKisCDDV3Y4GLGWBaoSCyD5uXkaUew6JDzA9FEN1W23mdnSwW9kqCeg==}
     engines: {node: '>=12'}
@@ -2323,6 +2550,7 @@ packages:
       '@esbuild/win32-arm64': 0.16.3
       '@esbuild/win32-ia32': 0.16.3
       '@esbuild/win32-x64': 0.16.3
+    dev: false
 
   /escalade/3.1.1:
     resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
@@ -3335,6 +3563,12 @@ packages:
     dependencies:
       '@jridgewell/sourcemap-codec': 1.4.14
 
+  /magic-string/0.29.0:
+    resolution: {integrity: sha512-WcfidHrDjMY+eLjlU+8OvwREqHwpgCeKVBUpQ3OhYYuvfaYCUgcbuBzappNzZvg/v8onU3oQj+BYpkOJe9Iw4Q==}
+    engines: {node: '>=12'}
+    dependencies:
+      '@jridgewell/sourcemap-codec': 1.4.14
+
   /make-dir/3.1.0:
     resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==}
     engines: {node: '>=8'}
@@ -3836,8 +4070,8 @@ packages:
       trouter: 3.2.0
     dev: true
 
-  /postcss/8.4.20:
-    resolution: {integrity: sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==}
+  /postcss/8.4.21:
+    resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==}
     engines: {node: ^10 || ^12 || >=14}
     dependencies:
       nanoid: 3.3.4
@@ -4137,6 +4371,13 @@ packages:
       estree-walker: 0.6.1
     dev: false
 
+  /rollup/3.15.0:
+    resolution: {integrity: sha512-F9hrCAhnp5/zx/7HYmftvsNBkMfLfk/dXUh73hPSM2E3CRgap65orDNJbLetoiUFwSAk6iHPLvBrZ5iHYvzqsg==}
+    engines: {node: '>=14.18.0', npm: '>=8.0.0'}
+    hasBin: true
+    optionalDependencies:
+      fsevents: 2.3.2
+
   /rollup/3.7.0:
     resolution: {integrity: sha512-FIJe0msW9P7L9BTfvaJyvn1U1BVCNTL3w8O+PKIrCyiMLg+rIUGb4MbcgVZ10Lnm1uWXOTOWRNARjfXC1+M12Q==}
     engines: {node: '>=14.18.0', npm: '>=8.0.0'}
@@ -4842,8 +5083,8 @@ packages:
       which-boxed-primitive: 1.0.2
     dev: true
 
-  /undici/5.18.0:
-    resolution: {integrity: sha512-1iVwbhonhFytNdg0P4PqyIAXbdlVZVebtPDvuM36m66mRw4OGrCm2MYynJv/UENFLdP13J1nPVQzVE2zTs1OeA==}
+  /undici/5.19.1:
+    resolution: {integrity: sha512-YiZ61LPIgY73E7syxCDxxa3LV2yl3sN8spnIuTct60boiiRaE1J8mNWHO8Im2Zi/sFrPusjLlmRPrsyraSqX6A==}
     engines: {node: '>=12.18'}
     dependencies:
       busboy: 1.6.0
@@ -4905,8 +5146,8 @@ packages:
       - rollup
     dev: true
 
-  /vite/4.0.4:
-    resolution: {integrity: sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==}
+  /vite/4.1.1:
+    resolution: {integrity: sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==}
     engines: {node: ^14.18.0 || >=16.0.0}
     hasBin: true
     peerDependencies:
@@ -4930,16 +5171,16 @@ packages:
       terser:
         optional: true
     dependencies:
-      esbuild: 0.16.3
-      postcss: 8.4.20
+      esbuild: 0.16.17
+      postcss: 8.4.21
       resolve: 1.22.1
-      rollup: 3.7.0
+      rollup: 3.15.0
     optionalDependencies:
       fsevents: 2.3.2
     dev: true
 
-  /vite/4.0.4_@types+node@16.18.6:
-    resolution: {integrity: sha512-xevPU7M8FU0i/80DMR+YhgrzR5KS2ORy1B4xcX/cXLsvnUWvfHuqMmVU6N0YiJ4JWGRJJsLCgjEzKjG9/GKoSw==}
+  /vite/4.1.1_@types+node@16.18.6:
+    resolution: {integrity: sha512-LM9WWea8vsxhr782r9ntg+bhSFS06FJgCvvB0+8hf8UWtvaiDagKYWXndjfX6kGl74keHJUcpzrQliDXZlF5yg==}
     engines: {node: ^14.18.0 || >=16.0.0}
     hasBin: true
     peerDependencies:
@@ -4964,14 +5205,14 @@ packages:
         optional: true
     dependencies:
       '@types/node': 16.18.6
-      esbuild: 0.16.3
-      postcss: 8.4.20
+      esbuild: 0.16.17
+      postcss: 8.4.21
       resolve: 1.22.1
-      rollup: 3.7.0
+      rollup: 3.15.0
     optionalDependencies:
       fsevents: 2.3.2
 
-  /vitefu/0.2.3_vite@4.0.4:
+  /vitefu/0.2.3_vite@4.1.1:
     resolution: {integrity: sha512-75l7TTuU8isAhz1QFtNKjDkqjxvndfMC1AfIMjJ0ZQ59ZD0Ow9QOIsJJX16Wv9PS8f+zMzp6fHy5cCbKG/yVUQ==}
     peerDependencies:
       vite: ^3.0.0 || ^4.0.0
@@ -4979,7 +5220,7 @@ packages:
       vite:
         optional: true
     dependencies:
-      vite: 4.0.4_@types+node@16.18.6
+      vite: 4.1.1_@types+node@16.18.6
     dev: false
 
   /vscode-oniguruma/1.6.2:
diff --git a/sites/kit.svelte.dev/package.json b/sites/kit.svelte.dev/package.json
index fa519838b..adcd13502 100644
--- a/sites/kit.svelte.dev/package.json
+++ b/sites/kit.svelte.dev/package.json
@@ -18,7 +18,7 @@
 		"@types/d3-geo": "^3.0.2",
 		"@types/node": "^16.18.6",
 		"flexsearch": "^0.7.31",
-		"magic-string": "^0.27.0",
+		"magic-string": "^0.29.0",
 		"marked": "^4.2.3",
 		"prism-svelte": "^0.5.0",
 		"prismjs": "^1.29.0",
@@ -27,7 +27,7 @@
 		"tiny-glob": "^0.2.9",
 		"typescript": "^4.9.4",
 		"uvu": "^0.5.6",
-		"vite": "^4.0.4",
+		"vite": "^4.1.1",
 		"vite-imagetools": "^4.0.16"
 	},
 	"type": "module",


Test patch:
diff --git a/packages/adapter-static/test/apps/prerendered/package.json b/packages/adapter-static/test/apps/prerendered/package.json
index 2bb623bad..f95d90c20 100644
--- a/packages/adapter-static/test/apps/prerendered/package.json
+++ b/packages/adapter-static/test/apps/prerendered/package.json
@@ -10,7 +10,7 @@
 	"devDependencies": {
 		"@sveltejs/kit": "workspace:^",
 		"svelte": "^3.55.1",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/adapter-static/test/apps/spa/package.json b/packages/adapter-static/test/apps/spa/package.json
index eba324ded..dbbe02ad6 100644
--- a/packages/adapter-static/test/apps/spa/package.json
+++ b/packages/adapter-static/test/apps/spa/package.json
@@ -12,7 +12,7 @@
 		"@sveltejs/kit": "workspace:^",
 		"sirv-cli": "^2.0.2",
 		"svelte": "^3.55.1",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/apps/amp/package.json b/packages/kit/test/apps/amp/package.json
index 85e7fdc2a..2b0ad36ff 100644
--- a/packages/kit/test/apps/amp/package.json
+++ b/packages/kit/test/apps/amp/package.json
@@ -19,7 +19,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/apps/basics/package.json b/packages/kit/test/apps/basics/package.json
index 5941e968a..8bccf89b2 100644
--- a/packages/kit/test/apps/basics/package.json
+++ b/packages/kit/test/apps/basics/package.json
@@ -20,7 +20,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/apps/dev-only/package.json b/packages/kit/test/apps/dev-only/package.json
index b5e510b23..450cb5ae7 100644
--- a/packages/kit/test/apps/dev-only/package.json
+++ b/packages/kit/test/apps/dev-only/package.json
@@ -15,7 +15,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/apps/options-2/package.json b/packages/kit/test/apps/options-2/package.json
index b55a3a6ab..b6022e8d0 100644
--- a/packages/kit/test/apps/options-2/package.json
+++ b/packages/kit/test/apps/options-2/package.json
@@ -18,7 +18,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/apps/options/package.json b/packages/kit/test/apps/options/package.json
index cbc2bab54..574812858 100644
--- a/packages/kit/test/apps/options/package.json
+++ b/packages/kit/test/apps/options/package.json
@@ -17,7 +17,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/apps/writes/package.json b/packages/kit/test/apps/writes/package.json
index 53b981b90..9f2ee0e1d 100644
--- a/packages/kit/test/apps/writes/package.json
+++ b/packages/kit/test/apps/writes/package.json
@@ -18,7 +18,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/build-errors/apps/prerenderable-incorrect-fragment/package.json b/packages/kit/test/build-errors/apps/prerenderable-incorrect-fragment/package.json
index 4173c40c2..0cf8d4f6c 100644
--- a/packages/kit/test/build-errors/apps/prerenderable-incorrect-fragment/package.json
+++ b/packages/kit/test/build-errors/apps/prerenderable-incorrect-fragment/package.json
@@ -14,7 +14,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/build-errors/apps/prerenderable-not-prerendered/package.json b/packages/kit/test/build-errors/apps/prerenderable-not-prerendered/package.json
index e42c7b09b..7a76362b1 100644
--- a/packages/kit/test/build-errors/apps/prerenderable-not-prerendered/package.json
+++ b/packages/kit/test/build-errors/apps/prerenderable-not-prerendered/package.json
@@ -14,7 +14,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/build-errors/apps/private-dynamic-env-dynamic-import/package.json b/packages/kit/test/build-errors/apps/private-dynamic-env-dynamic-import/package.json
index 7ac0f0169..614f1d39f 100644
--- a/packages/kit/test/build-errors/apps/private-dynamic-env-dynamic-import/package.json
+++ b/packages/kit/test/build-errors/apps/private-dynamic-env-dynamic-import/package.json
@@ -14,7 +14,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/build-errors/apps/private-dynamic-env/package.json b/packages/kit/test/build-errors/apps/private-dynamic-env/package.json
index e5ad0f712..3b8a9bb1c 100644
--- a/packages/kit/test/build-errors/apps/private-dynamic-env/package.json
+++ b/packages/kit/test/build-errors/apps/private-dynamic-env/package.json
@@ -14,7 +14,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/build-errors/apps/private-static-env-dynamic-import/package.json b/packages/kit/test/build-errors/apps/private-static-env-dynamic-import/package.json
index 539f7fc29..5b576909a 100644
--- a/packages/kit/test/build-errors/apps/private-static-env-dynamic-import/package.json
+++ b/packages/kit/test/build-errors/apps/private-static-env-dynamic-import/package.json
@@ -14,7 +14,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/build-errors/apps/private-static-env/package.json b/packages/kit/test/build-errors/apps/private-static-env/package.json
index 0c85a8151..8b57a78f1 100644
--- a/packages/kit/test/build-errors/apps/private-static-env/package.json
+++ b/packages/kit/test/build-errors/apps/private-static-env/package.json
@@ -15,7 +15,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/build-errors/apps/server-only-folder-dynamic-import/package.json b/packages/kit/test/build-errors/apps/server-only-folder-dynamic-import/package.json
index 6cb866bab..0718f79b0 100644
--- a/packages/kit/test/build-errors/apps/server-only-folder-dynamic-import/package.json
+++ b/packages/kit/test/build-errors/apps/server-only-folder-dynamic-import/package.json
@@ -14,7 +14,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/build-errors/apps/server-only-folder/package.json b/packages/kit/test/build-errors/apps/server-only-folder/package.json
index 3ad0d88ce..11dd1af87 100644
--- a/packages/kit/test/build-errors/apps/server-only-folder/package.json
+++ b/packages/kit/test/build-errors/apps/server-only-folder/package.json
@@ -14,7 +14,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/build-errors/apps/server-only-module-dynamic-import/package.json b/packages/kit/test/build-errors/apps/server-only-module-dynamic-import/package.json
index 417306e3f..e14ac0210 100644
--- a/packages/kit/test/build-errors/apps/server-only-module-dynamic-import/package.json
+++ b/packages/kit/test/build-errors/apps/server-only-module-dynamic-import/package.json
@@ -14,7 +14,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/build-errors/apps/server-only-module/package.json b/packages/kit/test/build-errors/apps/server-only-module/package.json
index 1afd11520..408e601fb 100644
--- a/packages/kit/test/build-errors/apps/server-only-module/package.json
+++ b/packages/kit/test/build-errors/apps/server-only-module/package.json
@@ -14,7 +14,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/build-errors/apps/syntax-error/package.json b/packages/kit/test/build-errors/apps/syntax-error/package.json
index 0d57ac6c9..2740222b8 100644
--- a/packages/kit/test/build-errors/apps/syntax-error/package.json
+++ b/packages/kit/test/build-errors/apps/syntax-error/package.json
@@ -12,7 +12,7 @@
 		"svelte": "^3.55.1",
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/prerendering/basics/package.json b/packages/kit/test/prerendering/basics/package.json
index 34810ff86..62cf5bd2e 100644
--- a/packages/kit/test/prerendering/basics/package.json
+++ b/packages/kit/test/prerendering/basics/package.json
@@ -16,7 +16,7 @@
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
 		"uvu": "^0.5.6",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/prerendering/options/package.json b/packages/kit/test/prerendering/options/package.json
index 4d3aaf18a..ced280561 100644
--- a/packages/kit/test/prerendering/options/package.json
+++ b/packages/kit/test/prerendering/options/package.json
@@ -15,7 +15,7 @@
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
 		"uvu": "^0.5.6",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/prerendering/paths-base/package.json b/packages/kit/test/prerendering/paths-base/package.json
index 66557d68d..99c2a1b0d 100644
--- a/packages/kit/test/prerendering/paths-base/package.json
+++ b/packages/kit/test/prerendering/paths-base/package.json
@@ -15,7 +15,7 @@
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
 		"uvu": "^0.5.6",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/kit/test/prerendering/ssr-false/package.json b/packages/kit/test/prerendering/ssr-false/package.json
index dc9b11514..f4f34b88f 100644
--- a/packages/kit/test/prerendering/ssr-false/package.json
+++ b/packages/kit/test/prerendering/ssr-false/package.json
@@ -15,7 +15,7 @@
 		"svelte-check": "^3.0.2",
 		"typescript": "^4.9.4",
 		"uvu": "^0.5.6",
-		"vite": "^4.0.4"
+		"vite": "^4.1.1"
 	},
 	"type": "module"
 }
diff --git a/packages/package/test/errors/duplicate-export/jsconfig.json b/packages/package/test/errors/duplicate-export/jsconfig.json
deleted file mode 100644
index f29fde21b..000000000
--- a/packages/package/test/errors/duplicate-export/jsconfig.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-	"compilerOptions": {
-		"checkJs": true,
-		"baseUrl": ".",
-		"paths": {
-			"$lib/*": ["./src/lib/*"]
-		}
-	},
-	"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
-}
diff --git a/packages/package/test/errors/duplicate-export/package.json b/packages/package/test/errors/duplicate-export/package.json
deleted file mode 100644
index 4befdcc6b..000000000
--- a/packages/package/test/errors/duplicate-export/package.json
+++ /dev/null
@@ -1,6 +0,0 @@
-{
-	"name": "error-duplicate-export",
-	"private": true,
-	"version": "1.0.0",
-	"description": "validate duplicate export error output"
-}
diff --git a/packages/package/test/errors/duplicate-export/src/lib/utils.ts b/packages/package/test/errors/duplicate-export/src/lib/utils.ts
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/errors/duplicate-export/src/lib/utils/index.js b/packages/package/test/errors/duplicate-export/src/lib/utils/index.js
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/errors/duplicate-export/svelte.config.js b/packages/package/test/errors/duplicate-export/svelte.config.js
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/errors/duplicate-export/tsconfig.json b/packages/package/test/errors/duplicate-export/tsconfig.json
deleted file mode 100644
index f29fde21b..000000000
--- a/packages/package/test/errors/duplicate-export/tsconfig.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
-	"compilerOptions": {
-		"checkJs": true,
-		"baseUrl": ".",
-		"paths": {
-			"$lib/*": ["./src/lib/*"]
-		}
-	},
-	"include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte"]
-}
diff --git a/packages/package/test/fixtures/assets/expected/package.json b/packages/package/test/fixtures/assets/expected/package.json
deleted file mode 100644
index 8cd8408fe..000000000
--- a/packages/package/test/fixtures/assets/expected/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "name": "assets",
-	"private": true,
-  "version": "1.0.0",
-  "description": "no tampering assets",
-  "type": "module",
-  "exports": {
-    "./package.json": "./package.json",
-    "./kit.png": "./kit.png"
-  }
-}
diff --git a/packages/package/test/fixtures/emitTypes-false/expected/package.json b/packages/package/test/fixtures/emitTypes-false/expected/package.json
deleted file mode 100644
index c4ccc94b1..000000000
--- a/packages/package/test/fixtures/emitTypes-false/expected/package.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-	"name": "emit-types",
-	"private": true,
-	"version": "1.0.0",
-	"description": "emitTypes settings disabled",
-	"type": "module",
-	"exports": {
-		"./package.json": "./package.json",
-		"./Test.svelte": "./Test.svelte",
-		"./Test2.svelte": "./Test2.svelte",
-		".": "./index.js"
-	},
-	"svelte": "./index.js"
-}
\ No newline at end of file
diff --git a/packages/package/test/fixtures/emitTypes-false/svelte.config.js b/packages/package/test/fixtures/emitTypes-false/svelte.config.js
index ff5361a7a..f7e83e849 100644
--- a/packages/package/test/fixtures/emitTypes-false/svelte.config.js
+++ b/packages/package/test/fixtures/emitTypes-false/svelte.config.js
@@ -1,7 +1,3 @@
-const config = {
-	package: {
-		emitTypes: false
-	}
-};
+const config = {};
 
 export default config;
diff --git a/packages/package/test/fixtures/exports-merge/expected/Test.svelte b/packages/package/test/fixtures/exports-merge/expected/Test.svelte
deleted file mode 100644
index e60789af6..000000000
--- a/packages/package/test/fixtures/exports-merge/expected/Test.svelte
+++ /dev/null
@@ -1,12 +0,0 @@
-<script>
-	import { createEventDispatcher } from 'svelte';
-	/**
-	 * @type {string}
-	 */
-	export const astring = 'potato';
-
-	const dispatch = createEventDispatcher();
-	dispatch('event', true);
-</script>
-
-<slot {astring} />
diff --git a/packages/package/test/fixtures/exports-merge/expected/Test.svelte.d.ts b/packages/package/test/fixtures/exports-merge/expected/Test.svelte.d.ts
deleted file mode 100644
index 71bb3d889..000000000
--- a/packages/package/test/fixtures/exports-merge/expected/Test.svelte.d.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-/** @typedef {typeof __propDef.props}  TestProps */
-/** @typedef {typeof __propDef.events}  TestEvents */
-/** @typedef {typeof __propDef.slots}  TestSlots */
-export default class Test extends SvelteComponentTyped<
-	{
-		astring?: string;
-	},
-	{
-		event: CustomEvent<any>;
-	} & {
-		[evt: string]: CustomEvent<any>;
-	},
-	{
-		default: {
-			astring: string;
-		};
-	}
-> {
-	get astring(): string;
-}
-export type TestProps = typeof __propDef.props;
-export type TestEvents = typeof __propDef.events;
-export type TestSlots = typeof __propDef.slots;
-import { SvelteComponentTyped } from 'svelte';
-declare const __propDef: {
-	props: {
-		astring?: string;
-	};
-	events: {
-		event: CustomEvent<any>;
-	} & {
-		[evt: string]: CustomEvent<any>;
-	};
-	slots: {
-		default: {
-			astring: string;
-		};
-	};
-};
-export {};
diff --git a/packages/package/test/fixtures/exports-merge/expected/hello-world.d.ts b/packages/package/test/fixtures/exports-merge/expected/hello-world.d.ts
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/fixtures/exports-merge/expected/hello-world.js b/packages/package/test/fixtures/exports-merge/expected/hello-world.js
deleted file mode 100644
index 08369f710..000000000
--- a/packages/package/test/fixtures/exports-merge/expected/hello-world.js
+++ /dev/null
@@ -1,1 +0,0 @@
-// hyphen in filename
diff --git a/packages/package/test/fixtures/exports-merge/expected/icons123.d.ts b/packages/package/test/fixtures/exports-merge/expected/icons123.d.ts
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/fixtures/exports-merge/expected/icons123.js b/packages/package/test/fixtures/exports-merge/expected/icons123.js
deleted file mode 100644
index 70161b512..000000000
--- a/packages/package/test/fixtures/exports-merge/expected/icons123.js
+++ /dev/null
@@ -1,1 +0,0 @@
-// numbers in filename
diff --git a/packages/package/test/fixtures/exports-merge/expected/index.d.ts b/packages/package/test/fixtures/exports-merge/expected/index.d.ts
deleted file mode 100644
index 4c44188c3..000000000
--- a/packages/package/test/fixtures/exports-merge/expected/index.d.ts
+++ /dev/null
@@ -1,1 +0,0 @@
-export { default as Test } from './Test.svelte';
diff --git a/packages/package/test/fixtures/exports-merge/expected/index.js b/packages/package/test/fixtures/exports-merge/expected/index.js
deleted file mode 100644
index 4c44188c3..000000000
--- a/packages/package/test/fixtures/exports-merge/expected/index.js
+++ /dev/null
@@ -1,1 +0,0 @@
-export { default as Test } from './Test.svelte';
diff --git a/packages/package/test/fixtures/exports-merge/expected/internal/Test.svelte b/packages/package/test/fixtures/exports-merge/expected/internal/Test.svelte
deleted file mode 100644
index 852fe8cd5..000000000
--- a/packages/package/test/fixtures/exports-merge/expected/internal/Test.svelte
+++ /dev/null
@@ -1,6 +0,0 @@
-<script>
-	/**
-	 * @type {import('./foo').Foo}
-	 */
-	export let foo;
-</script>
diff --git a/packages/package/test/fixtures/exports-merge/expected/internal/Test.svelte.d.ts b/packages/package/test/fixtures/exports-merge/expected/internal/Test.svelte.d.ts
deleted file mode 100644
index c6ff47603..000000000
--- a/packages/package/test/fixtures/exports-merge/expected/internal/Test.svelte.d.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/** @typedef {typeof __propDef.props}  TestProps */
-/** @typedef {typeof __propDef.events}  TestEvents */
-/** @typedef {typeof __propDef.slots}  TestSlots */
-export default class Test extends SvelteComponentTyped<
-	{
-		foo: boolean;
-	},
-	{
-		[evt: string]: CustomEvent<any>;
-	},
-	{}
-> {}
-export type TestProps = typeof __propDef.props;
-export type TestEvents = typeof __propDef.events;
-export type TestSlots = typeof __propDef.slots;
-import { SvelteComponentTyped } from 'svelte';
-declare const __propDef: {
-	props: {
-		foo: import('./foo').Foo;
-	};
-	events: {
-		[evt: string]: CustomEvent<any>;
-	};
-	slots: {};
-};
-export {};
diff --git a/packages/package/test/fixtures/exports-merge/expected/internal/_Private.svelte b/packages/package/test/fixtures/exports-merge/expected/internal/_Private.svelte
deleted file mode 100644
index 605c3c2de..000000000
--- a/packages/package/test/fixtures/exports-merge/expected/internal/_Private.svelte
+++ /dev/null
@@ -1,1 +0,0 @@
-This is a private component and should be excluded
diff --git a/packages/package/test/fixtures/exports-merge/expected/internal/_Private.svelte.d.ts b/packages/package/test/fixtures/exports-merge/expected/internal/_Private.svelte.d.ts
deleted file mode 100644
index 55647e2f8..000000000
--- a/packages/package/test/fixtures/exports-merge/expected/internal/_Private.svelte.d.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/** @typedef {typeof __propDef.props}  PrivateProps */
-/** @typedef {typeof __propDef.events}  PrivateEvents */
-/** @typedef {typeof __propDef.slots}  PrivateSlots */
-export default class Private extends SvelteComponentTyped<
-{
-	[x:string]: never;
-}, {
-	[evt: string]: CustomEvent<any>;
-},
-{}
-> {
-}
-export type PrivateProps = typeof __propDef.props;
-export type PrivateEvents = typeof __propDef.events;
-export type PrivateSlots = typeof __propDef.slots;
-import { SvelteComponentTyped } from "svelte";
-declare const __propDef: {
-	props: {
-		[x:string]: never;
-	};
-	events: {
-		[evt: string]: CustomEvent<any>;
-	};
-	slots: {};
-};
-export {};
diff --git a/packages/package/test/fixtures/exports-merge/expected/internal/constants.d.ts b/packages/package/test/fixtures/exports-merge/expected/internal/constants.d.ts
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/fixtures/exports-merge/expected/internal/constants.js b/packages/package/test/fixtures/exports-merge/expected/internal/constants.js
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/fixtures/exports-merge/expected/internal/foo.d.ts b/packages/package/test/fixtures/exports-merge/expected/internal/foo.d.ts
deleted file mode 100644
index c941ad7b1..000000000
--- a/packages/package/test/fixtures/exports-merge/expected/internal/foo.d.ts
+++ /dev/null
@@ -1,1 +0,0 @@
-export type Foo = boolean;
diff --git a/packages/package/test/fixtures/exports-merge/expected/package.json b/packages/package/test/fixtures/exports-merge/expected/package.json
deleted file mode 100644
index 085f6ac97..000000000
--- a/packages/package/test/fixtures/exports-merge/expected/package.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
-	"name": "exports-replace",
-	"private": true,
-	"version": "1.0.0",
-	"description": "merges exports field",
-	"exports": {
-		"./internal/constants": "./internal/constants.js",
-		"./internal/Test.svelte": "./internal/Test.svelte",
-		"./hello-world": "./hello-world.js",
-		"./icons123": "./icons123.js",
-		"./Test.svelte": "./Test.svelte",
-		"./why_underscore": "./why_underscore.js",
-		".": {
-			"import": "./index.js"
-		},
-		"./constants": "./internal/constants.js",
-		"./Test": "./Test.svelte",
-		"./package.json": "./package.json"
-	},
-	"type": "module",
-	"svelte": "./index.js"
-}
\ No newline at end of file
diff --git a/packages/package/test/fixtures/exports-merge/expected/why_underscore.d.ts b/packages/package/test/fixtures/exports-merge/expected/why_underscore.d.ts
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/fixtures/exports-merge/expected/why_underscore.js b/packages/package/test/fixtures/exports-merge/expected/why_underscore.js
deleted file mode 100644
index fb22c7cff..000000000
--- a/packages/package/test/fixtures/exports-merge/expected/why_underscore.js
+++ /dev/null
@@ -1,1 +0,0 @@
-// underscore in filename
diff --git a/packages/package/test/fixtures/exports-merge/jsconfig.json b/packages/package/test/fixtures/exports-merge/jsconfig.json
deleted file mode 100644
index 0967ef424..000000000
--- a/packages/package/test/fixtures/exports-merge/jsconfig.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{}
diff --git a/packages/package/test/fixtures/exports-merge/package.json b/packages/package/test/fixtures/exports-merge/package.json
deleted file mode 100644
index 0033602dd..000000000
--- a/packages/package/test/fixtures/exports-merge/package.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-	"name": "exports-replace",
-	"private": true,
-	"version": "1.0.0",
-	"description": "merges exports field",
-	"exports": {
-		".": {
-			"import": "./index.js"
-		},
-		"./constants": "./internal/constants.js",
-		"./Test": "./Test.svelte"
-	}
-}
diff --git a/packages/package/test/fixtures/exports-merge/src/lib/Test.svelte b/packages/package/test/fixtures/exports-merge/src/lib/Test.svelte
deleted file mode 100644
index e60789af6..000000000
--- a/packages/package/test/fixtures/exports-merge/src/lib/Test.svelte
+++ /dev/null
@@ -1,12 +0,0 @@
-<script>
-	import { createEventDispatcher } from 'svelte';
-	/**
-	 * @type {string}
-	 */
-	export const astring = 'potato';
-
-	const dispatch = createEventDispatcher();
-	dispatch('event', true);
-</script>
-
-<slot {astring} />
diff --git a/packages/package/test/fixtures/exports-merge/src/lib/hello-world.js b/packages/package/test/fixtures/exports-merge/src/lib/hello-world.js
deleted file mode 100644
index 08369f710..000000000
--- a/packages/package/test/fixtures/exports-merge/src/lib/hello-world.js
+++ /dev/null
@@ -1,1 +0,0 @@
-// hyphen in filename
diff --git a/packages/package/test/fixtures/exports-merge/src/lib/icons123.js b/packages/package/test/fixtures/exports-merge/src/lib/icons123.js
deleted file mode 100644
index 70161b512..000000000
--- a/packages/package/test/fixtures/exports-merge/src/lib/icons123.js
+++ /dev/null
@@ -1,1 +0,0 @@
-// numbers in filename
diff --git a/packages/package/test/fixtures/exports-merge/src/lib/index.js b/packages/package/test/fixtures/exports-merge/src/lib/index.js
deleted file mode 100644
index 4c44188c3..000000000
--- a/packages/package/test/fixtures/exports-merge/src/lib/index.js
+++ /dev/null
@@ -1,1 +0,0 @@
-export { default as Test } from './Test.svelte';
diff --git a/packages/package/test/fixtures/exports-merge/src/lib/internal/Test.svelte b/packages/package/test/fixtures/exports-merge/src/lib/internal/Test.svelte
deleted file mode 100644
index 852fe8cd5..000000000
--- a/packages/package/test/fixtures/exports-merge/src/lib/internal/Test.svelte
+++ /dev/null
@@ -1,6 +0,0 @@
-<script>
-	/**
-	 * @type {import('./foo').Foo}
-	 */
-	export let foo;
-</script>
diff --git a/packages/package/test/fixtures/exports-merge/src/lib/internal/_Private.svelte b/packages/package/test/fixtures/exports-merge/src/lib/internal/_Private.svelte
deleted file mode 100644
index 605c3c2de..000000000
--- a/packages/package/test/fixtures/exports-merge/src/lib/internal/_Private.svelte
+++ /dev/null
@@ -1,1 +0,0 @@
-This is a private component and should be excluded
diff --git a/packages/package/test/fixtures/exports-merge/src/lib/internal/constants.js b/packages/package/test/fixtures/exports-merge/src/lib/internal/constants.js
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/fixtures/exports-merge/src/lib/internal/foo.d.ts b/packages/package/test/fixtures/exports-merge/src/lib/internal/foo.d.ts
deleted file mode 100644
index c941ad7b1..000000000
--- a/packages/package/test/fixtures/exports-merge/src/lib/internal/foo.d.ts
+++ /dev/null
@@ -1,1 +0,0 @@
-export type Foo = boolean;
diff --git a/packages/package/test/fixtures/exports-merge/src/lib/why_underscore.js b/packages/package/test/fixtures/exports-merge/src/lib/why_underscore.js
deleted file mode 100644
index fb22c7cff..000000000
--- a/packages/package/test/fixtures/exports-merge/src/lib/why_underscore.js
+++ /dev/null
@@ -1,1 +0,0 @@
-// underscore in filename
diff --git a/packages/package/test/fixtures/exports-merge/svelte.config.js b/packages/package/test/fixtures/exports-merge/svelte.config.js
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/fixtures/exports-replace/expected/Test.svelte b/packages/package/test/fixtures/exports-replace/expected/Test.svelte
deleted file mode 100644
index e60789af6..000000000
--- a/packages/package/test/fixtures/exports-replace/expected/Test.svelte
+++ /dev/null
@@ -1,12 +0,0 @@
-<script>
-	import { createEventDispatcher } from 'svelte';
-	/**
-	 * @type {string}
-	 */
-	export const astring = 'potato';
-
-	const dispatch = createEventDispatcher();
-	dispatch('event', true);
-</script>
-
-<slot {astring} />
diff --git a/packages/package/test/fixtures/exports-replace/expected/Test.svelte.d.ts b/packages/package/test/fixtures/exports-replace/expected/Test.svelte.d.ts
deleted file mode 100644
index 71bb3d889..000000000
--- a/packages/package/test/fixtures/exports-replace/expected/Test.svelte.d.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-/** @typedef {typeof __propDef.props}  TestProps */
-/** @typedef {typeof __propDef.events}  TestEvents */
-/** @typedef {typeof __propDef.slots}  TestSlots */
-export default class Test extends SvelteComponentTyped<
-	{
-		astring?: string;
-	},
-	{
-		event: CustomEvent<any>;
-	} & {
-		[evt: string]: CustomEvent<any>;
-	},
-	{
-		default: {
-			astring: string;
-		};
-	}
-> {
-	get astring(): string;
-}
-export type TestProps = typeof __propDef.props;
-export type TestEvents = typeof __propDef.events;
-export type TestSlots = typeof __propDef.slots;
-import { SvelteComponentTyped } from 'svelte';
-declare const __propDef: {
-	props: {
-		astring?: string;
-	};
-	events: {
-		event: CustomEvent<any>;
-	} & {
-		[evt: string]: CustomEvent<any>;
-	};
-	slots: {
-		default: {
-			astring: string;
-		};
-	};
-};
-export {};
diff --git a/packages/package/test/fixtures/exports-replace/expected/index.d.ts b/packages/package/test/fixtures/exports-replace/expected/index.d.ts
deleted file mode 100644
index 4c44188c3..000000000
--- a/packages/package/test/fixtures/exports-replace/expected/index.d.ts
+++ /dev/null
@@ -1,1 +0,0 @@
-export { default as Test } from './Test.svelte';
diff --git a/packages/package/test/fixtures/exports-replace/expected/index.js b/packages/package/test/fixtures/exports-replace/expected/index.js
deleted file mode 100644
index 4c44188c3..000000000
--- a/packages/package/test/fixtures/exports-replace/expected/index.js
+++ /dev/null
@@ -1,1 +0,0 @@
-export { default as Test } from './Test.svelte';
diff --git a/packages/package/test/fixtures/exports-replace/expected/internal/Test.svelte b/packages/package/test/fixtures/exports-replace/expected/internal/Test.svelte
deleted file mode 100644
index 852fe8cd5..000000000
--- a/packages/package/test/fixtures/exports-replace/expected/internal/Test.svelte
+++ /dev/null
@@ -1,6 +0,0 @@
-<script>
-	/**
-	 * @type {import('./foo').Foo}
-	 */
-	export let foo;
-</script>
diff --git a/packages/package/test/fixtures/exports-replace/expected/internal/Test.svelte.d.ts b/packages/package/test/fixtures/exports-replace/expected/internal/Test.svelte.d.ts
deleted file mode 100644
index c6ff47603..000000000
--- a/packages/package/test/fixtures/exports-replace/expected/internal/Test.svelte.d.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/** @typedef {typeof __propDef.props}  TestProps */
-/** @typedef {typeof __propDef.events}  TestEvents */
-/** @typedef {typeof __propDef.slots}  TestSlots */
-export default class Test extends SvelteComponentTyped<
-	{
-		foo: boolean;
-	},
-	{
-		[evt: string]: CustomEvent<any>;
-	},
-	{}
-> {}
-export type TestProps = typeof __propDef.props;
-export type TestEvents = typeof __propDef.events;
-export type TestSlots = typeof __propDef.slots;
-import { SvelteComponentTyped } from 'svelte';
-declare const __propDef: {
-	props: {
-		foo: import('./foo').Foo;
-	};
-	events: {
-		[evt: string]: CustomEvent<any>;
-	};
-	slots: {};
-};
-export {};
diff --git a/packages/package/test/fixtures/exports-replace/expected/internal/foo.d.ts b/packages/package/test/fixtures/exports-replace/expected/internal/foo.d.ts
deleted file mode 100644
index c941ad7b1..000000000
--- a/packages/package/test/fixtures/exports-replace/expected/internal/foo.d.ts
+++ /dev/null
@@ -1,1 +0,0 @@
-export type Foo = boolean;
diff --git a/packages/package/test/fixtures/exports-replace/expected/package.json b/packages/package/test/fixtures/exports-replace/expected/package.json
deleted file mode 100644
index 45ec663ff..000000000
--- a/packages/package/test/fixtures/exports-replace/expected/package.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-	"name": "exports-replace",
-	"private": true,
-	"version": "1.0.0",
-	"description": "replaces exports field",
-	"type": "module",
-	"exports": {
-		".": {
-			"import": "./index.js"
-		},
-		"./package.json": "./package.json"
-	},
-	"svelte": "./Test.svelte"
-}
\ No newline at end of file
diff --git a/packages/package/test/fixtures/exports-replace/jsconfig.json b/packages/package/test/fixtures/exports-replace/jsconfig.json
deleted file mode 100644
index 0967ef424..000000000
--- a/packages/package/test/fixtures/exports-replace/jsconfig.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{}
diff --git a/packages/package/test/fixtures/exports-replace/package.json b/packages/package/test/fixtures/exports-replace/package.json
deleted file mode 100644
index 96c198738..000000000
--- a/packages/package/test/fixtures/exports-replace/package.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-	"name": "exports-replace",
-	"private": true,
-	"version": "1.0.0",
-	"description": "replaces exports field",
-	"type": "module",
-	"exports": {
-		".": {
-			"import": "./index.js"
-		}
-	},
-	"svelte": "./Test.svelte"
-}
diff --git a/packages/package/test/fixtures/exports-replace/src/lib/Test.svelte b/packages/package/test/fixtures/exports-replace/src/lib/Test.svelte
deleted file mode 100644
index e60789af6..000000000
--- a/packages/package/test/fixtures/exports-replace/src/lib/Test.svelte
+++ /dev/null
@@ -1,12 +0,0 @@
-<script>
-	import { createEventDispatcher } from 'svelte';
-	/**
-	 * @type {string}
-	 */
-	export const astring = 'potato';
-
-	const dispatch = createEventDispatcher();
-	dispatch('event', true);
-</script>
-
-<slot {astring} />
diff --git a/packages/package/test/fixtures/exports-replace/src/lib/index.js b/packages/package/test/fixtures/exports-replace/src/lib/index.js
deleted file mode 100644
index 4c44188c3..000000000
--- a/packages/package/test/fixtures/exports-replace/src/lib/index.js
+++ /dev/null
@@ -1,1 +0,0 @@
-export { default as Test } from './Test.svelte';
diff --git a/packages/package/test/fixtures/exports-replace/src/lib/internal/Test.svelte b/packages/package/test/fixtures/exports-replace/src/lib/internal/Test.svelte
deleted file mode 100644
index 852fe8cd5..000000000
--- a/packages/package/test/fixtures/exports-replace/src/lib/internal/Test.svelte
+++ /dev/null
@@ -1,6 +0,0 @@
-<script>
-	/**
-	 * @type {import('./foo').Foo}
-	 */
-	export let foo;
-</script>
diff --git a/packages/package/test/fixtures/exports-replace/src/lib/internal/foo.d.ts b/packages/package/test/fixtures/exports-replace/src/lib/internal/foo.d.ts
deleted file mode 100644
index c941ad7b1..000000000
--- a/packages/package/test/fixtures/exports-replace/src/lib/internal/foo.d.ts
+++ /dev/null
@@ -1,1 +0,0 @@
-export type Foo = boolean;
diff --git a/packages/package/test/fixtures/exports-replace/svelte.config.js b/packages/package/test/fixtures/exports-replace/svelte.config.js
deleted file mode 100644
index 8436b7fea..000000000
--- a/packages/package/test/fixtures/exports-replace/svelte.config.js
+++ /dev/null
@@ -1,7 +0,0 @@
-const config = {
-	package: {
-		exports: () => false
-	}
-};
-
-export default config;
diff --git a/packages/package/test/fixtures/files-exclude/expected/Test.svelte b/packages/package/test/fixtures/files-exclude/expected/Test.svelte
deleted file mode 100644
index e60789af6..000000000
--- a/packages/package/test/fixtures/files-exclude/expected/Test.svelte
+++ /dev/null
@@ -1,12 +0,0 @@
-<script>
-	import { createEventDispatcher } from 'svelte';
-	/**
-	 * @type {string}
-	 */
-	export const astring = 'potato';
-
-	const dispatch = createEventDispatcher();
-	dispatch('event', true);
-</script>
-
-<slot {astring} />
diff --git a/packages/package/test/fixtures/files-exclude/expected/Test.svelte.d.ts b/packages/package/test/fixtures/files-exclude/expected/Test.svelte.d.ts
deleted file mode 100644
index 71bb3d889..000000000
--- a/packages/package/test/fixtures/files-exclude/expected/Test.svelte.d.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-/** @typedef {typeof __propDef.props}  TestProps */
-/** @typedef {typeof __propDef.events}  TestEvents */
-/** @typedef {typeof __propDef.slots}  TestSlots */
-export default class Test extends SvelteComponentTyped<
-	{
-		astring?: string;
-	},
-	{
-		event: CustomEvent<any>;
-	} & {
-		[evt: string]: CustomEvent<any>;
-	},
-	{
-		default: {
-			astring: string;
-		};
-	}
-> {
-	get astring(): string;
-}
-export type TestProps = typeof __propDef.props;
-export type TestEvents = typeof __propDef.events;
-export type TestSlots = typeof __propDef.slots;
-import { SvelteComponentTyped } from 'svelte';
-declare const __propDef: {
-	props: {
-		astring?: string;
-	};
-	events: {
-		event: CustomEvent<any>;
-	} & {
-		[evt: string]: CustomEvent<any>;
-	};
-	slots: {
-		default: {
-			astring: string;
-		};
-	};
-};
-export {};
diff --git a/packages/package/test/fixtures/files-exclude/expected/index.d.ts b/packages/package/test/fixtures/files-exclude/expected/index.d.ts
deleted file mode 100644
index f0eb1f79b..000000000
--- a/packages/package/test/fixtures/files-exclude/expected/index.d.ts
+++ /dev/null
@@ -1,1 +0,0 @@
-export const hello: 'world';
diff --git a/packages/package/test/fixtures/files-exclude/expected/index.js b/packages/package/test/fixtures/files-exclude/expected/index.js
deleted file mode 100644
index 35f468bf4..000000000
--- a/packages/package/test/fixtures/files-exclude/expected/index.js
+++ /dev/null
@@ -1,1 +0,0 @@
-export const hello = 'world';
diff --git a/packages/package/test/fixtures/files-exclude/expected/internal/index.d.ts b/packages/package/test/fixtures/files-exclude/expected/internal/index.d.ts
deleted file mode 100644
index e60ad9862..000000000
--- a/packages/package/test/fixtures/files-exclude/expected/internal/index.d.ts
+++ /dev/null
@@ -1,1 +0,0 @@
-export const foo: 'bar';
diff --git a/packages/package/test/fixtures/files-exclude/expected/internal/index.js b/packages/package/test/fixtures/files-exclude/expected/internal/index.js
deleted file mode 100644
index c155820bf..000000000
--- a/packages/package/test/fixtures/files-exclude/expected/internal/index.js
+++ /dev/null
@@ -1,1 +0,0 @@
-export const foo = 'bar';
diff --git a/packages/package/test/fixtures/files-exclude/expected/package.json b/packages/package/test/fixtures/files-exclude/expected/package.json
deleted file mode 100644
index 2303af531..000000000
--- a/packages/package/test/fixtures/files-exclude/expected/package.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-	"name": "files-exclude",
-	"private": true,
-	"version": "1.0.0",
-	"description": "files.exclude settings configured",
-	"type": "module",
-	"exports": {
-		"./package.json": "./package.json",
-		"./internal": "./internal/index.js",
-		"./Test.svelte": "./Test.svelte",
-		".": "./index.js"
-	},
-	"svelte": "./index.js"
-}
\ No newline at end of file
diff --git a/packages/package/test/fixtures/files-exclude/jsconfig.json b/packages/package/test/fixtures/files-exclude/jsconfig.json
deleted file mode 100644
index 0967ef424..000000000
--- a/packages/package/test/fixtures/files-exclude/jsconfig.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{}
diff --git a/packages/package/test/fixtures/files-exclude/package.json b/packages/package/test/fixtures/files-exclude/package.json
deleted file mode 100644
index c81333c30..000000000
--- a/packages/package/test/fixtures/files-exclude/package.json
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-	"name": "files-exclude",
-	"private": true,
-	"version": "1.0.0",
-	"description": "files.exclude settings configured",
-	"type": "module"
-}
diff --git a/packages/package/test/fixtures/files-exclude/src/lib/Test.exclude.svelte b/packages/package/test/fixtures/files-exclude/src/lib/Test.exclude.svelte
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/fixtures/files-exclude/src/lib/Test.svelte b/packages/package/test/fixtures/files-exclude/src/lib/Test.svelte
deleted file mode 100644
index e60789af6..000000000
--- a/packages/package/test/fixtures/files-exclude/src/lib/Test.svelte
+++ /dev/null
@@ -1,12 +0,0 @@
-<script>
-	import { createEventDispatcher } from 'svelte';
-	/**
-	 * @type {string}
-	 */
-	export const astring = 'potato';
-
-	const dispatch = createEventDispatcher();
-	dispatch('event', true);
-</script>
-
-<slot {astring} />
diff --git a/packages/package/test/fixtures/files-exclude/src/lib/check.mjs b/packages/package/test/fixtures/files-exclude/src/lib/check.mjs
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/fixtures/files-exclude/src/lib/empty/Test.exclude.svelte b/packages/package/test/fixtures/files-exclude/src/lib/empty/Test.exclude.svelte
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/fixtures/files-exclude/src/lib/exclude.js b/packages/package/test/fixtures/files-exclude/src/lib/exclude.js
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/fixtures/files-exclude/src/lib/index.js b/packages/package/test/fixtures/files-exclude/src/lib/index.js
deleted file mode 100644
index 35f468bf4..000000000
--- a/packages/package/test/fixtures/files-exclude/src/lib/index.js
+++ /dev/null
@@ -1,1 +0,0 @@
-export const hello = 'world';
diff --git a/packages/package/test/fixtures/files-exclude/src/lib/internal/build.mjs b/packages/package/test/fixtures/files-exclude/src/lib/internal/build.mjs
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/fixtures/files-exclude/src/lib/internal/exclude.js b/packages/package/test/fixtures/files-exclude/src/lib/internal/exclude.js
deleted file mode 100644
index e69de29bb..000000000
diff --git a/packages/package/test/fixtures/files-exclude/src/lib/internal/index.js b/packages/package/test/fixtures/files-exclude/src/lib/internal/index.js
deleted file mode 100644
index c155820bf..000000000
--- a/packages/package/test/fixtures/files-exclude/src/lib/internal/index.js
+++ /dev/null
@@ -1,1 +0,0 @@
-export const foo = 'bar';
diff --git a/packages/package/test/fixtures/files-exclude/svelte.config.js b/packages/package/test/fixtures/files-exclude/svelte.config.js
deleted file mode 100644
index 3f46f0e40..000000000
--- a/packages/package/test/fixtures/files-exclude/svelte.config.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const config = {
-	package: {
-		files(filepath) {
-			const ext = filepath.slice(filepath.lastIndexOf('.') + 1);
-			if (ext === 'js' || ext === 'svelte') return !filepath.includes('exclude');
-			return ext !== 'mjs';
-		}
-	}
-};
-
-export default config;
diff --git a/packages/package/test/fixtures/javascript/expected/ReadMe.md b/packages/package/test/fixtures/javascript/expected/ReadMe.md
deleted file mode 100644
index e965047ad..000000000
--- a/packages/package/test/fixtures/javascript/expected/ReadMe.md
+++ /dev/null
@@ -1,1 +0,0 @@
-Hello
diff --git a/packages/package/test/fixtures/javascript/expected/package.json b/packages/package/test/fixtures/javascript/expected/package.json
deleted file mode 100644
index bbabe850c..000000000
--- a/packages/package/test/fixtures/javascript/expected/package.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-	"name": "javascript",
-	"private": true,
-	"version": "1.0.0",
-	"description": "standard javascript package",
-	"type": "module",
-	"exports": {
-		"./package.json": "./package.json",
-		"./internal": "./internal/index.js",
-		"./internal/Test.svelte": "./internal/Test.svelte",
-		"./Test.svelte": "./Test.svelte",
-		"./Test2.svelte": "./Test2.svelte",
-		"./utils": "./utils.js",
-		".": "./index.js"
-	},
-	"svelte": "./index.js"
-}
\ No newline at end of file
diff --git a/packages/package/test/fixtures/resolve-alias/expected/package.json b/packages/package/test/fixtures/resolve-alias/expected/package.json
deleted file mode 100644
index b0cea47c9..000000000
--- a/packages/package/test/fixtures/resolve-alias/expected/package.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-	"name": "resolve-alias",
-	"private": true,
-	"version": "1.0.0",
-	"description": "package using $lib alias",
-	"type": "module",
-	"exports": {
-		"./package.json": "./package.json",
-		"./Test.svelte": "./Test.svelte",
-		"./utils": "./utils/index.js",
-		".": "./index.js",
-		"./baz": "./baz.js",
-		"./sub/bar": "./sub/bar.js",
-		"./sub/foo": "./sub/foo.js"
-	},
-	"svelte": "./index.js"
-}
diff --git a/packages/package/test/fixtures/svelte-kit/expected/package.json b/packages/package/test/fixtures/svelte-kit/expected/package.json
deleted file mode 100644
index 9a4640878..000000000
--- a/packages/package/test/fixtures/svelte-kit/expected/package.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
-	"name": "svelte-kit",
-	"private": true,
-	"version": "1.0.0",
-	"type": "module",
-	"description": "SvelteKit library project",
-	"exports": {
-		"./package.json": "./package.json",
-		"./Test.svelte": "./Test.svelte",
-		".": "./index.js"
-	},
-	"svelte": "./index.js"
-}
\ No newline at end of file
diff --git a/packages/package/test/fixtures/typescript/expected/package.json b/packages/package/test/fixtures/typescript/expected/package.json
deleted file mode 100644
index 91b6a3b5b..000000000
--- a/packages/package/test/fixtures/typescript/expected/package.json
+++ /dev/null
@@ -1,16 +0,0 @@
-{
-	"name": "typescript",
-	"private": true,
-	"version": "1.0.0",
-	"description": "standard typescript package",
-	"type": "module",
-	"exports": {
-		"./package.json": "./package.json",
-		"./Plain.svelte": "./Plain.svelte",
-		"./Test.svelte": "./Test.svelte",
-		"./Test2.svelte": "./Test2.svelte",
-		"./utils": "./utils.js",
-		".": "./index.js"
-	},
-	"svelte": "./index.js"
-}
\ No newline at end of file
diff --git a/packages/package/test/index.js b/packages/package/test/index.js
index 6a06e24bb..a0ab8b4b3 100644
--- a/packages/package/test/index.js
+++ b/packages/package/test/index.js
@@ -15,42 +15,48 @@ const __dirname = join(__filename, '..');
 
 /**
  * @param {string} path
+ * @param {Partial<import('../src/types').Options>} [options]
  */
-async function test_make_package(path) {
+async function test_make_package(path, options) {
 	const cwd = join(__dirname, 'fixtures', path);
 	const ewd = join(cwd, 'expected');
-	const pwd = join(cwd, 'package');
+	const output = join(cwd, 'dist');
 
-	try {
-		const config = await load_config({ cwd });
-		config.package.dir = resolve(cwd, config.package.dir);
-
-		await build(config, cwd);
-		const expected_files = walk(ewd, true);
-		const actual_files = walk(pwd, true);
-
-		assert.equal(actual_files, expected_files);
-
-		const extensions = ['.json', '.svelte', '.ts', 'js'];
-		for (const file of actual_files) {
-			const pathname = join(pwd, file);
-			if (fs.statSync(pathname).isDirectory()) continue;
-			assert.ok(expected_files.includes(file), `Did not expect ${file} in ${path}`);
-
-			const expected = fs.readFileSync(join(ewd, file));
-			const actual = fs.readFileSync(join(pwd, file));
-			const err_msg = `Expected equal file contents for ${file} in ${path}`;
-
-			if (extensions.some((ext) => pathname.endsWith(ext))) {
-				const expected_content = format(file, expected.toString('utf-8'));
-				const actual_content = format(file, actual.toString('utf-8'));
-				assert.fixture(actual_content, expected_content, err_msg);
-			} else {
-				assert.ok(expected.equals(actual), err_msg);
-			}
+	const config = await load_config({ cwd });
+
+	const input = resolve(cwd, config.kit?.files?.lib ?? 'src/lib');
+
+	await build({
+		cwd,
+		input,
+		output,
+		types: true,
+		config,
+		...options
+	});
+
+	const expected_files = walk(ewd, true);
+	const actual_files = walk(output, true);
+
+	assert.equal(actual_files, expected_files);
+
+	const extensions = ['.json', '.svelte', '.ts', 'js'];
+	for (const file of actual_files) {
+		const pathname = join(output, file);
+		if (fs.statSync(pathname).isDirectory()) continue;
+		assert.ok(expected_files.includes(file), `Did not expect ${file} in ${path}`);
+
+		const expected = fs.readFileSync(join(ewd, file));
+		const actual = fs.readFileSync(join(output, file));
+		const err_msg = `Expected equal file contents for ${file} in ${path}`;
+
+		if (extensions.some((ext) => pathname.endsWith(ext))) {
+			const expected_content = format(file, expected.toString('utf-8'));
+			const actual_content = format(file, actual.toString('utf-8'));
+			assert.fixture(actual_content, expected_content, err_msg);
+		} else {
+			assert.ok(expected.equals(actual), err_msg);
 		}
-	} finally {
-		rimraf(pwd);
 	}
 }
 
@@ -75,26 +81,24 @@ function format(file, content) {
 for (const dir of fs.readdirSync(join(__dirname, 'errors'))) {
 	test(`package error [${dir}]`, async () => {
 		const cwd = join(__dirname, 'errors', dir);
-		const pwd = join(cwd, 'package');
+		const output = join(cwd, 'dist');
 
 		const config = await load_config({ cwd });
-		config.package.dir = resolve(cwd, config.package.dir);
+
+		const input = resolve(cwd, config.kit?.files?.lib ?? 'src/lib');
 
 		try {
-			await build(config, cwd);
+			await build({ cwd, input, output, types: true, config });
 			assert.unreachable('Must not pass build');
 		} catch (/** @type {any} */ error) {
 			assert.instance(error, Error);
 			switch (dir) {
-				case 'duplicate-export':
+				case 'no-lib-folder':
 					assert.match(
-						error.message,
-						'Duplicate "./utils" export. Please remove or rename either $lib/utils/index.js or $lib/utils.ts'
+						error.message.replace(/\\/g, '/'),
+						`test/errors/no-lib-folder/src/lib does not exist`
 					);
 					break;
-				case 'no-lib-folder':
-					assert.match(error.message, `${join(cwd, 'src', 'lib')} does not exist`);
-					break;
 				// TODO: non-existent tsconfig passes without error
 				// 	it detects tsconfig in packages/kit instead and creates package folder
 				// 	in packages/kit/package, not sure how to handle and test this yet
@@ -107,7 +111,7 @@ for (const dir of fs.readdirSync(join(__dirname, 'errors'))) {
 					break;
 			}
 		} finally {
-			rimraf(pwd);
+			rimraf(output);
 		}
 	});
 }
@@ -127,19 +131,7 @@ test('create package and assets are not tampered', async () => {
 });
 
 test('create package with emitTypes settings disabled', async () => {
-	await test_make_package('emitTypes-false');
-});
-
-test('create package and properly merge exports map', async () => {
-	await test_make_package('exports-merge');
-});
-
-test('create package and properly exclude all exports', async () => {
-	await test_make_package('exports-replace');
-});
-
-test('create package with files.exclude settings', async () => {
-	await test_make_package('files-exclude');
+	await test_make_package('emitTypes-false', { types: false });
 });
 
 test('create package and resolves $lib alias', async () => {
@@ -156,9 +148,14 @@ if (!process.env.CI) {
 		const cwd = join(__dirname, 'watch');
 
 		const config = await load_config({ cwd });
-		config.package.dir = resolve(cwd, config.package.dir);
 
-		const { watcher, ready, settled } = await watch(config, cwd);
+		const { watcher, ready, settled } = await watch({
+			cwd,
+			input: 'src/lib',
+			output: 'package',
+			types: true,
+			config
+		});
 
 		/** @param {string} file */
 		function compare(file) {