Skip to content

Instantly share code, notes, and snippets.

@lnfel
Last active July 30, 2024 02:46
Show Gist options
  • Save lnfel/6f6cb71d42bf8da01fc30178bcaba74d to your computer and use it in GitHub Desktop.
Save lnfel/6f6cb71d42bf8da01fc30178bcaba74d to your computer and use it in GitHub Desktop.
Publishing an NPM package using svelte-package.

Publish NPM package using svelte-package

Svelte kit makes it easier to publish packages on npm using svelte-package. We can both have the npm package and docs web page in a single repo. Svelte also automatically generate types for our svelte component and js files.

  1. Create Svelte project
pnpm create svelte@latest my-package
  1. CD into the project
cd my-package
  1. Create some component (src/lib/components/AwesomeComponent.svelte) or export something from src/lib/index.js file.

Important

Note that we need to re-export components in lib/index.js too!

  1. We then need Nodejs to know where is the entry point of our package. By default running svelte-package outputs src/lib files to dist folder at the root of the project folder. We need to define an exports field in our packcage.json file pointing to those files in the dist folder.
"exports": {
  ".": {
    "types": "./dist/index.d.ts",
    "svelte": "./dist/index.js"
  },
  "./dist/components/LamyDebugbar.svelte": {
    "types": "./dist/components/AwesomeComponent.svelte.d.ts",
    "svelte": "./dist/components/AwesomeComponent.svelte"
  }
}

Note

The "exports" field is used to restrict external access to non-exported module files, also enables a module to import itself using "name".

The above exports mapping also ties the types to our svelte and js files. Typically exports would be written as:

"exports": {
  ".": "./lib/index.js",
}

But with Community Condition Definitions such as the types field we can tell yping systems to resolve the typing file for the given export.

Also see nodejs docs for Community Conditions Definitions

  1. Run svelte-package command (this is provided by @sveltejs/package package).
// To make our lives easier, let's put the svelte-package command in package.json scripts
"scripts": {
    "package": "svelte-kit sync && svelte-package && publint",
    "prepublishOnly": "npm run package",
}

Now we can run the command like so:

pnpm package

Tip

Running pnpm package does the following:

  1. svelte-kit sync Synchronises generated type definitions
  2. svelte-package Packages/copies src/lib to ./dist folder by default
  3. publint Checks for linting errors Note that we no longer need to copy package.json to package dist/output folder.

Note

Take note of the prepublishOnly script as it will be run automatically when running npm publish later.

See NPM Life Cycle Scripts

  1. Add a files property in package.json file and add ["dist"] as the property value.
// package.json
"files": [
    "dist"
],

Note

If there is a "files" list in package.json, then only the files specified will be included. (If directories are specified, then they will be walked recursively and their contents included, subject to the same ignore rules.). In this case only dist folder will be included when we publish to npm. Certain files that are relevant to package installation and distribution are always included such as package.json, README.md, LICENSE, and so on.

See npm publish - Files included in package

  1. Finally login with npm cli via npm login and simply run npm publish --access public The default tag is latest. If publishing a release candidate or beta version run the command with --tag flag

Tip

To publish a version preview of a package i.e. x.0.0-next.1

npm publish --tag next --access public

Use the word next, beta or rc etc. depending on your context.

Our npm package will then have the following structure on npmjs website:

package-name/
├── dist/
│   ├── components/
│   │   ├── AwesomeComponent.svelte.d.ts
│   │   └── AwesomeComponent.svelte
│   ├── some-file.d.ts
│   ├── some-file.js
│   ├── index.d.ts
│   └── index.js
├── LICENSE
├── README.md
└── package.json
// inside src/lib/index.js
/**
* We are re-exporting the component as default. Consumers of the package can then import it like:
* ```js
* import AwesomeComponent from 'package-name'
* ```
*/
import AwesomeComponent from "./components/AwesomeComponent.svelte"
export default AwesomeComponent
/**
* Or using a one-liner shortcut to re-export the component
* Note that it is not exported as default this time, users will need to import it like:
* ```js
* import { AwesomeComponent } from 'package-name'
* ```
*/
// export { default as AwesomeComponent } from "./components/AwesomeComponent.svelte"
/**
* Do not forget to re-export core methods provided by your package it there is any.
*/
export { someMethod, anotherMethod } from './some-file.js'
/**
* Or if the package is small, no need to have separate file. Simply export it inline on this file.
*/
export const coolerMethod = () => {}
{
"name": "package-name",
"description": "",
"type": "module",
"version": "0.0.1",
"author": "Author name or organization",
"license": "MIT or something else",
"homepage": "https://link-to-package.website/or-docs",
"repository": {
"type": "git",
"url": "https://github.com/github-repo-username/repo-name.git"
},
"keywords": ["related-tag-for-the-package"],
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"package": "svelte-kit sync && svelte-package && publint",
"prepublishOnly": "npm run package",
"check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch",
"test:unit": "vitest",
"lint": "prettier --plugin-search-dir . --check .",
"format": "prettier --plugin-search-dir . --write .",
"gh:deploy": "npm run build && pnpm dlx [email protected] -d build -t true",
"npm:publish": "npm publish --access public"
},
"exports": {
".": {
"types": "./dist/index.d.ts",
"svelte": "./dist/index.js"
},
"./dist/components/LamyDebugbar.svelte": {
"types": "./dist/components/AwesomeComponent.svelte.d.ts",
"svelte": "./dist/components/AwesomeComponent.svelte"
}
},
"files": [
"dist"
],
"peerDependencies": {
"@sveltejs/kit": "^1.27.6 || ^2.5.18",
"svelte": "^4.2.7 || ^5.0.0-next.1"
},
"svelte": "./dist/index.js",
"types": "./dist/index.d.ts",
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment