Skip to content

Package setup

All the Codey packages focus to support ESM & TS. The packages are also tree shackable to lower the imported size.

The Codey packages need to be used on different levels, internal and external.

Internal

Inside the mono-repo itself we will be using the packages too. Most packages depend on other packages to work correctly. For this we need to keep the source files (.vue, .ts, ...) available and configured in the package.json on the root of that package. This can be done by setting the main and exports option in the package.json file to the index file in the src folder.

Which makes it possible to import those files inside the mono-repo, without the need of building the package itself.

json
{
  ...
  "main": "./src/index.ts",
  "exports": "./src/index.ts",
  ...
}

External

The Codey packages are build for external use in other Vue and/or Node projects. This mean they have to ship ESM and CommonJS files. (More about this at Output format).

Packages will be build in the dist folder, to have them ready for tree shaking, they are created as seperate modules. To do this, we add a package.json file with the module setup in. A changelog.md file is also added to supply an overview of changes on that package.

The package.json file is generated during the build step of the package, thanks to the ViteModuleBuilder function from the @xerius/codey-internal-node package. Which sets the config options right, for example the main and exports option is different than the package.json in the root of the package.

Tree shaking

Tree shaking is a term commonly used within a JavaScript context to describe the removal of dead code.

It relies on the import and export statements to detect if code modules are exported and imported for use between JavaScript files. Read more about Tree shaking here.

Vite

We use the bundler feature of Vite to build the Codey packages. More information about Vite in library mode here.

Output format

The default output file format for Codey packages is ESM and CommonJS. This is set inside the vite.build file where ViteModuleBuilder is called as its params.

Package layout for internal use

Each of the Codey packages will need to provide a way to import them inside the Codey monorepo itself. You can configure this by setting the following options in the package.json file of that package.

json
{
  "type": "module"
  "main": "./src/index.js" // default es modules
  "exports": {
      "import":"./src/index.js"
    },
}

Based on: https://nodejs.org/api/packages.html#conditional-exports

Package layout for library

Each of the Codey packages will be exported so they can be imported in other Xerius projects. You can configure this by setting the following option in the package.json file of that package.

For JavaScript packages

json
{
  "type": "module"
  "main": "./index.js" // default es modules
  "exports": {
    "import": "./index.js",
    "require": "./index.cjs"
  },
}

For Vue packages

INFO

The chosen approach only outputs ESM and no commonJS. As we do not intend the components to be used directly in the browser.

For more information about this decision, check out the ADL record within the repo.

src structure

There is a main index file in the src folder that represents the entrypoint used by the package.json for internal use. This imports all available component modules, which allows them to remain tree shakeable.

This gives the following src structure:

- src/
  - button/
    - button.vue
    - index.ts
  index.ts

where src/index.ts contains:

ts
export * from "./button";

and src/button/index.ts contains:

ts
export { default as XerButton } from "./button.vue";

Building dist

For creating the dist output we don't simply build the root src/index.ts file. Doing so would create a single module of all components killing the tree shaking features of the library.

Instead we run vite build on every module within the source folder create the same structure within the dist folder with the build output.

The src/index.ts file is copied and renamed to dist/index.js as and esm entry point.

A package.json is also created set with this entrypoint.

This results in the following structure within the dist folder:

- dist/
  - button/
    - index.js
  index.js
  package.json

Vite config

Using vite as our build tool, we created a module builder to handle building separate modules in order to support our packages structure.

INFO

It is possible that vite will support this out of the box at some point. At the time of writing, multiple entry points that result in multiple outputs isn't supported.

vite.base-config.js

The vite.base-config.js is the config file for Vite. Please do not rename this file to vite.config.js as it will clash with running the programmatically build in vite.build.js.

ts
import path from "path";
import { fileURLToPath } from "url";
import vue from "@vitejs/plugin-vue";
import { defineConfig } from "vite";
import { externalizeDeps, createVitestConfig } from "@xerius/codey-internal-node";

const __dirname = path.dirname(fileURLToPath(import.meta.url));

export default {
  plugins: [externalizeDeps(), vue()],
  build: {
    outDir: "./dist", // lib & emptyOutDir controlled by vite.build.js
  },
  test: createVitestConfig(path.resolve(__dirname, "./../../reports/components")),
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
      "@support": path.resolve(__dirname, "./cypress/support"),
    },
  },
  // Server config is present for Cypress component testing
  server: {
    port: 5200,
    fs: {
      allow: ["./../../"], // Allow imports from outside this module, used by cypress
    },
  },
};

Resources