Skip to content

Commit

Permalink
[breaking] move packaging functionality into its own package (#5730)
Browse files Browse the repository at this point in the history
* [breaking] move package command into separate package

* enhance create-svelte with libskeleton option

* remove package from kit

* update docs

* move shared code into internal package

* update workflow to build shared first

* please?

* remove cyclic dependency

* fixes

* fix

* @internal/shared is a no-go since we no longer bundle, unless we publish it to npm which feels like overkill

* remove bundling

* fix workflow

* goddammit vscode grow up. just add the extension. sheesh

* update tests

* pin vite version for now, to avoid distracting test failures

* fix

* add unused prepare script

Co-authored-by: Rich Harris <hello@rich-harris.dev>
  • Loading branch information
dummdidumm and Rich-Harris committed Aug 17, 2022
1 parent ad0ffa2 commit 89ef569
Show file tree
Hide file tree
Showing 253 changed files with 845 additions and 268 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ test-results/
package-lock.json
yarn.lock
/packages/create-svelte/template/CHANGELOG.md
/packages/kit/src/packaging/test/watch/package
/packages/package/test/**/package
/documentation/types.js
.env
.vercel_build_output
Expand Down
6 changes: 3 additions & 3 deletions .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@
"files": [
"**/CHANGELOG.md",
"**/.svelte-kit/**",
"packages/kit/src/packaging/test/fixtures/**/expected/**/*",
"packages/kit/src/packaging/test/watch/expected/**/*",
"packages/kit/src/packaging/test/watch/package/**/*",
"packages/package/test/fixtures/**/expected/**/*",
"packages/package/test/watch/expected/**/*",
"packages/package/test/watch/package/**/*",
"packages/kit/src/core/prerender/fixtures/**/*",
"packages/migrate/migrations/routes/*/samples.md"
],
Expand Down
10 changes: 6 additions & 4 deletions documentation/docs/13-packaging.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@
title: Packaging
---

> `svelte-kit package` is currently experimental and is not subject to Semantic Versioning rules. Non-backward compatible changes may occur in any future release.
> `svelte-package` is currently experimental. Non-backward compatible changes may occur in any future release.
You can use SvelteKit to build component libraries as well as apps.
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`](/docs/modules#$lib) contains your app's internal library.

A SvelteKit 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.

Running `svelte-kit package` will take the contents of `src/lib` and generate a `package` directory (which can be [configured](/docs/configuration#package)) containing the following:
Running the `svelte-package` command from `@sveltejs/package` will take the contents of `src/lib` and generate a `package` directory (which can be [configured](/docs/configuration#package)) containing the following:

- All the files in `src/lib`, unless you [configure](/docs/configuration#package) 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` and `svelte2tsx >= 0.4.1` for this. Type definitions are placed next to their implementation, hand-written `d.ts` files are copied over as is. You can [disable generation](/docs/configuration#package), but we strongly recommend against it.
- 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](/docs/configuration#package), but we strongly recommend against it.
- 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.

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](/docs/configuration#package) this behaviour. If you have a `src/lib/index.js` or `src/lib/index.svelte` file, it will be treated as the package root.
Expand Down Expand Up @@ -50,4 +50,6 @@ The `./package` above is referring to the directory name generated, change accor

### 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.

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.
36 changes: 19 additions & 17 deletions documentation/docs/15-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,6 @@ const config = {
},
moduleExtensions: ['.js', '.ts'],
outDir: '.svelte-kit',
package: {
dir: 'package',
emitTypes: true,
// excludes all .d.ts and files starting with _ as the name
exports: (filepath) => !/^_|\/_|\.d\.ts$/.test(filepath),
files: () => true
},
paths: {
assets: '',
base: ''
Expand All @@ -80,7 +73,17 @@ const config = {
},

// options passed to svelte.preprocess (https://svelte.dev/docs#compile-time-svelte-preprocess)
preprocess: null
preprocess: null,

// options passed to @sveltejs/package
package: {
source: 'value of kit.files.lib, if available, else src/lib',
dir: 'package',
emitTypes: true,
// excludes all .d.ts and files starting with _ as the name
exports: (filepath) => !/^_|\/_|\.d\.ts$/.test(filepath),
files: () => true
}
};

export default config;
Expand Down Expand Up @@ -208,8 +211,9 @@ The directory that SvelteKit writes files to during `dev` and `build`. You shoul

Options related to [creating a package](/docs/packaging).

- `source` - library directory
- `dir` - output directory
- `emitTypes` - by default, `svelte-kit package` will automatically generate types for your package in the form of `.d.ts` files. While generating types is configurable, we believe it is best for the ecosystem quality to generate types, always. Please make sure you have a good reason when setting it to `false` (for example when you want to provide handwritten type definitions instead)
- `emitTypes` - by default, `svelte-package` will automatically generate types for your package in the form of `.d.ts` files. While generating types is configurable, we believe it is best for the ecosystem quality to generate types, always. Please make sure you have a good reason when setting it to `false` (for example when you want to provide handwritten type definitions instead)
- `exports` - a function with the type of `(filepath: string) => boolean`. When `true`, the filepath will be included in the `exports` field of the `package.json`. Any existing values in the `package.json` source will be merged with values from the original `exports` field taking precedence
- `files` - a function with the type of `(filepath: string) => boolean`. When `true`, the file will be processed and copied over to the final output folder, specified in `dir`

Expand All @@ -226,14 +230,12 @@ import mm from 'micromatch';

/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
package: {
exports: (filepath) => {
if (filepath.endsWith('.d.ts')) return false;
return mm.isMatch(filepath, ['!**/_*', '!**/internal/**']);
},
files: mm.matcher('!**/build.*')
}
package: {
exports: (filepath) => {
if (filepath.endsWith('.d.ts')) return false;
return mm.isMatch(filepath, ['!**/_*', '!**/internal/**']);
},
files: mm.matcher('!**/build.*')
}
};

Expand Down
2 changes: 1 addition & 1 deletion packages/adapter-static/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
"svelte": "^3.48.0",
"typescript": "^4.7.4",
"uvu": "^0.5.3",
"vite": "^3.0.0"
"vite": "3.0.2"
}
}
2 changes: 1 addition & 1 deletion packages/adapter-static/test/apps/prerendered/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"devDependencies": {
"@sveltejs/kit": "workspace:*",
"svelte": "^3.48.0",
"vite": "^3.0.0"
"vite": "3.0.2"
},
"type": "module"
}
2 changes: 1 addition & 1 deletion packages/adapter-static/test/apps/spa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"@sveltejs/kit": "workspace:*",
"sirv-cli": "^2.0.2",
"svelte": "^3.48.0",
"vite": "^3.0.0"
"vite": "3.0.2"
},
"type": "module"
}
24 changes: 22 additions & 2 deletions packages/create-svelte/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ function write_common_files(cwd, options, name) {
const pkg_file = path.join(cwd, 'package.json');
const pkg = /** @type {any} */ (JSON.parse(fs.readFileSync(pkg_file, 'utf-8')));

files.forEach((file) => {
sort_files(files).forEach((file) => {
const include = file.include.every((condition) => matches_condition(condition, options));
const exclude = file.exclude.some((condition) => matches_condition(condition, options));

Expand Down Expand Up @@ -83,7 +83,7 @@ function write_common_files(cwd, options, name) {
* @returns {boolean}
*/
function matches_condition(condition, options) {
if (condition === 'default' || condition === 'skeleton') {
if (condition === 'default' || condition === 'skeleton' || condition === 'libskeleton') {
return options.template === condition;
}
if (condition === 'typescript' || condition === 'checkjs') {
Expand Down Expand Up @@ -135,6 +135,26 @@ function sort_keys(obj) {
return sorted;
}

/**
* Sort files so that those which apply more generically come first so they
* can be overwritten by files for more precise cases later.
*
* @param files {import('./types/internal').Common['files']}
* */
function sort_files(files) {
return files.sort((f1, f2) => {
const f1_more_generic =
f1.include.every((include) => f2.include.includes(include)) &&
f1.exclude.every((exclude) => f2.exclude.includes(exclude));
const f2_more_generic =
f2.include.every((include) => f1.include.includes(include)) &&
f2.exclude.every((exclude) => f1.exclude.includes(exclude));
const same = f1_more_generic && f2_more_generic;
const different = !f1_more_generic && !f2_more_generic;
return same || different ? 0 : f1_more_generic ? -1 : 1;
});
}

/** @param {string} name */
function to_valid_package_name(name) {
return name
Expand Down
14 changes: 14 additions & 0 deletions packages/create-svelte/shared/+libskeleton+checkjs/jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "NodeNext"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "NodeNext"
}
}
1 change: 0 additions & 1 deletion packages/create-svelte/templates/default/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"scripts": {
"dev": "vite dev",
"build": "vite build",
"package": "svelte-kit package",
"preview": "vite preview"
},
"devDependencies": {
Expand Down
8 changes: 8 additions & 0 deletions packages/create-svelte/templates/libskeleton/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
3 changes: 3 additions & 0 deletions packages/create-svelte/templates/libskeleton/.ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package.json
.meta.json
.turbo
4 changes: 4 additions & 0 deletions packages/create-svelte/templates/libskeleton/.meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"title": "Library skeleton project",
"description": "Barebones scaffolding for your new Svelte library"
}
1 change: 1 addition & 0 deletions packages/create-svelte/templates/libskeleton/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engine-strict=true
18 changes: 18 additions & 0 deletions packages/create-svelte/templates/libskeleton/package.template.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "~TODO~",
"version": "0.0.1",
"scripts": {
"dev": "vite dev",
"build": "svelte-kit sync && svelte-package"
},
"devDependencies": {
"@sveltejs/adapter-auto": "workspace:*",
"@sveltejs/kit": "workspace:*",
"@sveltejs/package": "workspace:*",
"svelte": "^3.44.0",
"tslib": "^2.3.1",
"typescript": "^4.7.4",
"vite": "^3.0.0"
},
"type": "module"
}
11 changes: 11 additions & 0 deletions packages/create-svelte/templates/libskeleton/src/app.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/// <reference types="@sveltejs/kit" />

// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
// and what to do when importing types
declare namespace App {
// interface Locals {}
// interface Platform {}
// interface Session {}
// interface Stuff {}
}
12 changes: 12 additions & 0 deletions packages/create-svelte/templates/libskeleton/src/app.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body>
<div>%sveltekit.body%</div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// Reexport your entry components here
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<h1>Welcome to your library project</h1>
<p>Create your package using @sveltejs/package and preview/showcase your work with SvelteKit</p>
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions packages/create-svelte/templates/libskeleton/svelte.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import adapter from '@sveltejs/adapter-auto';

// This config is ignored and replaced with one of the configs in the shared folder when a project is created.

/** @type {import('@sveltejs/package').Config} */
const config = {
kit: {
adapter: adapter()
}
};

export default config;
8 changes: 8 additions & 0 deletions packages/create-svelte/templates/libskeleton/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { sveltekit } from '@sveltejs/kit/vite';

/** @type {import('vite').UserConfig} */
const config = {
plugins: [sveltekit()]
};

export default config;
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"name": "~TODO~",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "vite dev",
"build": "vite build",
"package": "svelte-kit package",
"preview": "vite preview"
},
"devDependencies": {
Expand Down
5 changes: 3 additions & 2 deletions packages/create-svelte/types/internal.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export type Options = {
name: string;
template: 'default' | 'skeleton';
template: 'default' | 'skeleton' | 'libskeleton';
types: 'typescript' | 'checkjs' | null;
prettier: boolean;
eslint: boolean;
Expand All @@ -19,7 +19,8 @@ export type Condition =
| 'checkjs'
| 'playwright'
| 'skeleton'
| 'default';
| 'default'
| 'libskeleton';

export type Common = {
files: Array<{
Expand Down
9 changes: 4 additions & 5 deletions packages/kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@
"rollup": "^2.75.7",
"svelte": "^3.48.0",
"svelte-preprocess": "^4.10.6",
"svelte2tsx": "~0.5.10",
"tiny-glob": "^0.2.9",
"typescript": "^4.7.4",
"uvu": "^0.5.3",
"vite": "^3.0.0"
"vite": "3.0.2"
},
"peerDependencies": {
"svelte": "^3.44.0",
"vite": "^3.0.0"
"vite": "3.0.2"
},
"bin": {
"svelte-kit": "svelte-kit.js"
Expand All @@ -66,10 +66,9 @@
"check:all": "tsc && pnpm -r --filter=\"./**\" check",
"format": "npm run lint -- --write",
"prepublishOnly": "npm run build",
"test": "npm run test:unit && npm run test:packaging && npm run test:integration",
"test": "npm run test:unit && npm run test:integration",
"test:integration": "pnpm run -r --workspace-concurrency 1 --filter=\"./test/**\" test",
"test:unit": "uvu src \"(spec\\.js|test[\\\\/]index\\.js)\" -i packaging",
"test:packaging": "uvu src/packaging \"(spec\\.js|test[\\\\/]index\\.js)\"",
"types": "node scripts/extract-types.js",
"postinstall": "node svelte-kit.js sync"
},
Expand Down
Loading

0 comments on commit 89ef569

Please sign in to comment.