📘 DOC: New "Publish to npm" documentation (#1323)
* new publish docs * Minor cleanup - Removed trailing whitespaces. - Fixed a typo where `components` was misspelled. - Moved all links to references at the bottom of the file. - On line 162, I added bash for the file tree example as it was used for the previous example on line 29. - Added a new line between examples that had a DO and DO NOT. - The code snippet from line 85 is a good example. Having that li'l space made it much nicer to read. * cleanup publish docs * add note on experimental nature of npm package support Co-authored-by: Devin W. Leaman <git@4lch4.email>
This commit is contained in:
parent
8707d1a4f2
commit
bf4ba7c3ee
3 changed files with 139 additions and 54 deletions
|
@ -24,8 +24,8 @@ export const SIDEBAR = {
|
|||
{ text: 'RSS', link: 'guides/rss' },
|
||||
{ text: 'Supported Imports', link: 'guides/imports' },
|
||||
{ text: 'Aliases', link: 'guides/aliases' },
|
||||
{ text: 'Deploy a Website', link: 'guides/deploy' },
|
||||
{ text: 'Publish a Component', link: 'guides/publish-to-npm' },
|
||||
{ text: 'Deploy to the web', link: 'guides/deploy' },
|
||||
{ text: 'Publish to npm', link: 'guides/publish-to-npm' },
|
||||
|
||||
{ text: 'Reference', header: true },
|
||||
{ text: 'Built-In Components', link: 'reference/builtin-components' },
|
||||
|
|
|
@ -1,101 +1,182 @@
|
|||
---
|
||||
layout: ~/layouts/MainLayout.astro
|
||||
title: Publish a Component to NPM
|
||||
title: Publish to NPM
|
||||
---
|
||||
|
||||
Built a great Astro component? **Publish it to [npm!](https://npmjs.com/)**
|
||||
Building a new Astro component? **Publish it to [npm!][NPM]**
|
||||
|
||||
Once published to npm, Astro components can be installed and used in your project like any other npm package. npm is a great way to share Astro components across projects within your team, your company, or the entire world.
|
||||
Publishing a component is a great way to reuse work across your team, your company, or the entire world. Astro components can be published to and installed from npm, just like any other JavaScript package.
|
||||
|
||||
## Basic NPM Package Setup
|
||||
**Astro's ability to publish and reuse popular UI components is one of it's most powerful features!**
|
||||
|
||||
Here's an example package that we'd like to publish to npm. It includes two Astro components and a few other files.
|
||||
Even if you don't plan on publishing your components online, the patterns outlined below can help any developer design reusable UI components in isolation from their custom website or business logic.
|
||||
|
||||
> **Note - Experimental:** Published npm components are still marked as experimental and some features are not yet supported. Astro component styles are currently disabled inside of npm packages, and JSX components must be compiled to `.js` in the package.
|
||||
|
||||
## Featured packages
|
||||
Looking for inspiration? Check out some of [our favorite themes & components][Themes] from the Astro community. You can also [search npm][Published-Astro-Components] to see the entire public catalog.
|
||||
|
||||
## Folder layout
|
||||
|
||||
Below is our recommended folder layout for package development. The example below shows a single package named `package-name` but you can add more folders to the `packages/` directory to develop multiple packages together in the same repo:
|
||||
|
||||
```bash
|
||||
packages/
|
||||
└─ package-name/
|
||||
├─ package.json
|
||||
├─ index.js
|
||||
├─ Capitalize.astro
|
||||
└─ Bold.astro
|
||||
public/
|
||||
# see "Developing your package" below.
|
||||
src/
|
||||
# see "Developing your package" below.
|
||||
```
|
||||
/my-components-package/
|
||||
├── package.json
|
||||
├── index.js
|
||||
├── Capitalize.astro
|
||||
└── Bold.astro
|
||||
```
|
||||
|
||||
Lets explore the different files that will make up your package:
|
||||
|
||||
### `package.json`
|
||||
|
||||
Your package manifest. This includes information about your package such as name, description, any dependencies, and other important metadata. If you don't know what the `package.json` file is, we highly recommend you to have a quick read on [the npm documentation](https://docs.npmjs.com/creating-a-package-json-file).
|
||||
Your package `package.json` file is known as your **package manifest.** Every package published to npm has one. This includes important configuration such as name, description, dependencies, and other package metadata. To publish anything to npm, it helps to have [a basic understanding][Creating-A-Package.json] of this JSON manifest format.
|
||||
|
||||
When making a astro component use the `astro-component` keyword, this makes it easier for people to find your component.
|
||||
#### Recommended: "keywords"
|
||||
|
||||
We recommend that you define an [exports entry](https://nodejs.org/api/packages.html) for your `index.js` package entrypoint like so:
|
||||
When publishing an Astro component, include the `astro-component` keyword in your package.json file. This makes it easier for people to [find your component on npm][Published-Astro-Components] and other search catalogs.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "@example/my-components",
|
||||
"version": "0.0.1",
|
||||
"exports": "./index.js",
|
||||
"keywords": ["astro-component"]
|
||||
"keywords": ["astro-component", ...]
|
||||
}
|
||||
```
|
||||
|
||||
#### Recommended: "exports"
|
||||
|
||||
We **strongly recommend** that you include an [exports entry][Node-Packages-API] in your `package.json`. This entry controls access to internal package files, and gives you more control over how users can import your package.
|
||||
|
||||
```json
|
||||
{
|
||||
"exports": "./index.js"
|
||||
}
|
||||
```
|
||||
|
||||
### `index.js`
|
||||
|
||||
`index.js` is your package entrypoint, which is the file that gets loaded when someone imports your package by name. Having a JavaScript file as your package entrypoint will let you export multiple components and have better control over their exported component names.
|
||||
We **strongly recommend** that every Astro package include an `index.js` file known as the **package entrypoint**. This is the file defined in your package `"exports"` entry (see above) that gets loaded when a user imports your package by name. Using a JavaScript entrypoint file lets you package multiple Astro components together into a single interface:
|
||||
|
||||
```js
|
||||
// Example package entrypoint: index.js
|
||||
// This lets users do: `import {Capitalize} from 'package-name';`
|
||||
export { default as Capitalize } from './Capitalize.astro';
|
||||
export { default as Bold } from './Bold.astro';
|
||||
// also supported: React, Svelte, Vue, etc.:
|
||||
export { default as Italic } from './SomeReactComponent.jsx';
|
||||
```
|
||||
|
||||
### Publishing
|
||||
### What about individual file imports?
|
||||
|
||||
Once you have your package ready, you can publish it to npm by running the command `npm publish`. If that fails, make sure that you've logged in via `npm login` and that your package.json is correct.
|
||||
We **strongly recommend** that you use an `index.js` package entrypoint to avoid individual file imports:
|
||||
|
||||
Once published, anyone will be able to install your components and then import them like so:
|
||||
```js
|
||||
// ✅ Do this:
|
||||
import {Bold, Capitalize} from 'package-name';
|
||||
|
||||
```astro
|
||||
---
|
||||
import { Bold, Capitalize } from '@example/my-components';
|
||||
---
|
||||
<Capitalize phrase={`Hello world`} />
|
||||
// ❌ Avoid this:
|
||||
import Bold from 'package-name/Bold.astro';
|
||||
import Capitalize from 'package-name/Capitalize.astro';
|
||||
```
|
||||
|
||||
## Advanced
|
||||
Astro is rendered at build-time, so there should be no performance impact for the user when you use a single `index.js` entrypoint file like this. For any components that do get loaded in the browser, you can trust that Astro's production bundler will optimize and remove any unused imports.
|
||||
|
||||
We recommend a single `index.js` package entrypoint because this is what most users are familiar with. However, in some rare scenarios you may want to have your users import each `.astro` component directly, in the same manner that you import `.astro` files in your own project.
|
||||
|
||||
```astro
|
||||
---
|
||||
import Capitalize from '@example/my-components/Capitalize.astro';
|
||||
---
|
||||
<Capitalize phrase={`Hello world`} />
|
||||
```
|
||||
|
||||
This is a less common scenario, and we only recommend it if you have good reason. Because Astro is completely rendered at build-time, there are no client-side performance concerns to our default recommendation to export your components from a single `index.js` file.
|
||||
|
||||
To support importing by file within your package, add each file to your **package.json** `exports` map:
|
||||
If you need to use individual file imports, be sure to add those files to your package manifest's `exports` entry:
|
||||
|
||||
```diff
|
||||
{
|
||||
"name": "@example/my-components",
|
||||
"name": "@example/my-package",
|
||||
"version": "1.0.0",
|
||||
"exports": {
|
||||
- ".": "./index.js",
|
||||
- "exports": "./index.js"
|
||||
+ "exports": {
|
||||
+ "./Bold.astro": "./Bold.astro",
|
||||
+ "./Capitalize.astro": "./Capitalize.astro"
|
||||
}
|
||||
+ }
|
||||
}
|
||||
```
|
||||
|
||||
## Community components
|
||||
## Developing your package
|
||||
|
||||
Looking for components already made by the community?
|
||||
Astro does not have a dedicated "package mode" for development. Instead, you should use a demo project to develop and test your package inside of the repo. This can be a private website only used for development, or a public demo/documentation website for your package.
|
||||
|
||||
Here are the current available community developed Astro components.
|
||||
If you are extracting components from an existing project, you can even continue to use that project to develop your now-extracted components.
|
||||
|
||||
- [Astro Static Tweet](https://www.npmjs.com/package/@rebelchris/astro-static-tweet) ~ A component to embed tweets as static HTML so you don't have to load the Twitter JavaScripts.
|
||||
- [Accessible Astro Components](https://www.npmjs.com/package/accessible-astro-components) ~ A set of accessible front-end components such as Accordions, Modals, Toggle Buttons and more.
|
||||
For development, we **strongly recommend** that you setup a [**project workspace.**][Node-Packages-Workspace] Workspaces are a feature supported by all package managers including npm (v7+), yarn, pnpm and others. A workspace will help you verify package.json configuration and also let you import your package by name:
|
||||
|
||||
You can also [search npm for astro components.](https://www.npmjs.com/search?q=keywords%3Aastro-component)
|
||||
```js
|
||||
// ✅ With workspaces:
|
||||
import {Bold, Capitalize} from 'package-name';
|
||||
|
||||
Did you make a component?
|
||||
// ❌ Without workspaces:
|
||||
import {Bold, Capitalize} from '../../../my-package-directory/index.js';
|
||||
```
|
||||
|
||||
[Create a PR to submit your component in these docs](https://github.com/snowpackjs/astro/issues/new/choose)
|
||||
To turn your project into a workspace, create a `package.json` file at the top-most level of your repository (if one doesn't already exist) and add a `"workspaces"` entry that identifies your `packages/` directory as a collection of packages:
|
||||
|
||||
```diff
|
||||
{
|
||||
"name": "my-workspace",
|
||||
"Description": "this is the package.json that sits at the top-level of your repo.",
|
||||
+ "workspaces": ["./packages/*"]
|
||||
}
|
||||
```
|
||||
|
||||
Save this change, and re-run your package manager's "install" command to set up your new workspace. If everything went well, you can now import your workspace packages by name.
|
||||
|
||||
You can optionally choose to move your development website's `src/` and `public/` directories into a workspace directory of their own. This is optional, and only recommended if you are familiar with how workspaces work.
|
||||
|
||||
```diff
|
||||
{
|
||||
"name": "my-workspace",
|
||||
"Description": "this is the package.json that sits at the top-level of your repo.",
|
||||
"workspaces": [
|
||||
"./packages/*",
|
||||
+ "./demo"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Testing your component
|
||||
|
||||
Astro does not currently ship a test runner. This is something that we would like to tackle before our v1.0 release. *(If you are interested in helping out, [join us on Discord!][Astro-Discord])*
|
||||
|
||||
In the meantime, our current recommendation for testing is:
|
||||
|
||||
1. Add a test "fixtures" directory to your `src/pages` directory.
|
||||
2. Add a new page for every test that you'd like to run.
|
||||
3. Each page should include some different component usage that you'd like to test.
|
||||
4. Run `astro build` to build your fixtures, then compare the output of the `dist/__fixtures__/` directory to what you expected.
|
||||
|
||||
```bash
|
||||
src/pages/__fixtures__/
|
||||
├─ test-name-01.astro
|
||||
├─ test-name-02.astro
|
||||
└─ test-name-03.astro
|
||||
```
|
||||
|
||||
## Publishing your component
|
||||
|
||||
Once you have your package ready, you can publish it to npm!
|
||||
|
||||
To publish a package to npm, use the `npm publish` command. If that fails, make sure that you've logged in via `npm login` and that your package.json is correct. If it succeeds, you're done!
|
||||
|
||||
Notice that there was no `build` step for Astro packages. Any file type that Astro supports can be published directly without a build step, because we know that Astro already supports them natively. This includes all files with extensions like `.astro`, `.ts`, `.jsx`, and `.css`.
|
||||
|
||||
If you need some other file type that isn't natively supported by Astro, you are welcome to add a build step to your package. This advanced exercise is left up to you.
|
||||
|
||||
[Themes]: /themes
|
||||
[NPM]: https://npmjs.com/
|
||||
[Accessible-Astro-Components]: https://www.npmjs.com/package/accessible-astro-components
|
||||
[Astro-Static-Tweet]: https://www.npmjs.com/package/@rebelchris/astro-static-tweet
|
||||
[Astro-SEO]: https://github.com/jonasmerlin/astro-seo
|
||||
[Published-Astro-Components]: https://www.npmjs.com/search?q=keywords%3Aastro-component
|
||||
[Creating-A-Package.json]: https://docs.npmjs.com/creating-a-package-json-file
|
||||
[Node-Packages-API]: https://nodejs.org/api/packages.html
|
||||
[Node-Packages-Workspace]: https://docs.npmjs.com/cli/v7/configuring-npm/package-json#workspaces
|
||||
[Astro-Discord]: https://astro.build/chat
|
||||
|
|
|
@ -37,4 +37,8 @@ import components from '../data/components.json';
|
|||
<div class="card-grid">
|
||||
{components.community.map((item)=>(<Card data={item} />))}
|
||||
</div>
|
||||
<Markdown>
|
||||
> Want to see your own work featured? [Share it to Discord!](https://astro.build/chat)
|
||||
We'll often take our favorites from the `#showcase` channel and post them here.
|
||||
</Markdown>
|
||||
</Layout>
|
Loading…
Reference in a new issue