# Vue 3 + TypeScript + Vite Component Library Starter

## Steps

### Scaffold the project
```bash
cd my-project-folder
# Scaffold directly into the folder
npm create vite@latest . -- --template vue-ts
# Install dependencies
npm install

# Include node types which are needed whenever you need to import from node
npm i --save-dev @types/node

## Update `package.json`
- Change name to `@username/projectname` to publish into your user scope.
- Remove `"private": true,` to allow publishing
- Specify `vue` as a peer dependency.

```json
  "peerDependencies": {
    "vue": "^3.0.0"
  },
```

- Add `dist` and optionally `src` to `files` to be published.

```json
  "files": [
    "dist",
    "src"
  ],
```

- Add `author`, `license`, `repository`, `keywords` for package information.

```json
  "author": "your-user-name",
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/your-user-name/your-repo-name.git"
  },
  "keywords": [
    "vue"
  ],
  ```

- Add `exports` fields to indicate how the package can be imported. Also mentions how types can be loaded.

```json
  "exports": {
    ".": {
      "types": "./dist/types/index.d.ts",
      "import": "./dist/your-component-name.es.js",
      "require": "./dist/your-component-name.umd.js"
    },
    "./style.css": "./dist/your-component-name.css"
  }
```

## Update `vite.config.ts`
Add the build config. An important setting includes `emptyOutDir`, which means do not clean the `dist` folder when building JS files by Vite. This is because we let vue-tsc emit the type declarations and let Vite emit the JS files.

```ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from "path";

// https://vite.dev/config/
export default defineConfig({
  plugins: [vue()],
  build: {
    lib: {
      entry: path.resolve(__dirname, "src/index.ts"),
      name: "YourComponentName",
      fileName: (format) => `your-component-name.${format}.js`,
    },
    rollupOptions: {
      external: ["vue"],
      output: {
        exports: "named",
        globals: {
          vue: "Vue",
        },
      },
    },
    emptyOutDir: false, // to retain the types folder generated by tsc
  },
})
```

Since Vite will not help to empty out the folder, we need to update `package.json` to help do that.

```json
    "build": "rm -rf dist && vue-tsc -b && vite build",
```

## Add `index.ts`
Include an entry point, to allow it to be both used globally or individually.

```ts
import type { App } from "vue";
import HelloWorld from "./components/HelloWorld.vue";

export { HelloWorld };

export default {
  install(app: App) {
    app.component("HelloWorld", HelloWorld);
  },
};
```


## Update `tsconfig.app.json`

The `tsconfig.app.json` is the one that we intend to use for building our component. The `tsconfig.node.json` is for any other development TypeScript files.

Set `"noEmit": false` so that type declarations can be emitted. This is set to `true` by default in the base config that we extend from. Other important settings include `"emitDeclarationOnly": true` to only emit type files.

```ts
{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "compilerOptions": {
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",

    /* Linting */
    "strict": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedSideEffectImports": true,

    /* Type Declaration */
    "noEmit": false, // This is important to generate type declaration files
    "emitDeclarationOnly": true, // This prevents the generation of JS files, which is left to vite
    "declaration": true,
    "declarationMap": true,
    "outDir": "dist/types",
    "rootDir": "src"
  },
  "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
  "exclude": ["node_modules", "dist"]
}
```

## Remove unused files
Remove the default files that are not needed, e.g., `App.vue, main.ts, style.css, src/assets/, index.html`.

## Publish
```bash
# Update version in package.json as needed
npm run build
npm publish --access public
```

## Usage
Make sure to import the `style.css` if your component contains css styles.

```ts
import { YourComponentName } from '@user-name/your-component-name'
import '@user-name/your-component-name/style.css'
```