For contributors
Architecture
Section titled “Architecture”Project structure
Section titled “Project structure”This project is a monorepo with the following structure:
apps- applications.docs- documentation website.
demos- demos.all- meta-package for all demos.inline- inline demos for various pages outside of specific framework context.*- demos for each supported framework.
packages- loader itself, integrations and internal utilities.integration-utils- utility functions and constants for integrations. They are exposed to the user viavite-awesome-svg-loader/integration-utilspackage. This makes it possible to write custom integrations.loader- loader’s source code.types- types for usage throughout the project.common-utils- various utilities for usage throughout the project. They are exposed to the user viavite-awesome-svg-loader/common-utilspackage for convenience.internal-utils- utilities for internal usage only.*-integration- specific framework integration.vite-astro-entry-generator- a plugin that generates an Astro component that loads a script on the client side.vite-awesome-svg-loader- final loader bundle (in other words, meta-package).vite-file-tree-builder- a plugin that builds a project’s file tree.
tests- tests.scripts- build scripts.modules.d.ts- types for untyped external modules.
Monorepo management
Section titled “Monorepo management”Turborepo is used to manage monorepo.
Demos are self-contained packages.
All demos should contain their own scripts and assets. The code and the assets are often duplicated across the demos.
When a demo is built, its file tree is generated and displayed in the docs website.
Demos should be small and should not have a sprawling file tree.
Demos are built in Vite library mode and consumed by the apps/docs
package.
This pattern avoids the need to run multiple web servers for live reload and simplifies build process.
Scripts
Section titled “Scripts”generate-sources- generates project’s source code required for building. Runs automatically before any other build command.build- builds whole project.build:packages- builds all packages. Use this while developing to speed up the build.build:apps- builds all apps.build:demos- builds all demos.dev- builds all packages and runs alldevcommands. This command is resource-heavy!dev:docs:standalone- runsdevcommand fordocspackages without running all demos in watch mode. This is a lighter alternative todev. The docs are still updated whenever demo is rebuilt.test- runs the tests.lint- lints the code with ESLint.format- formats the code with Prettier.
TypeScript and JavaScript
Section titled “TypeScript and JavaScript”The primary language for this project is TypeScript. TypeScript should be used while the developing loader itself, integrations and demos.
However, build scripts are written in JS to simplify development and speed up the build. Typing is not crucial for these scripts. Thus, TypeScript is not necessary.
Bundlers
Section titled “Bundlers”Vite is the primary bundler for this project.
Other bundlers may be used if Vite ecosystem doesn’t have a solution, or if specific package requires specific tooling.
For example, docs app uses Astro and its tooling (it’s Vite internally, but this may change in future).
Custom build scripts and/or plugins may be used in the build process. Ideally, custom additions to the build process should be implemented as bundler’s plugins or build lifecycle hooks. But plain JS scripts are fine if they’re suited better for the job.
Bundle structure
Section titled “Bundle structure”Every project (package, demo or app) should be bundled into a dist directory inside the project’s root.
For example, packages/utils bundle should be in packages/utils/dist directory.
Dependencies
Section titled “Dependencies”Dependencies that are used by more than one project should be installed for the whole project (added to the root
package.json).
Such dependencies include Vite, TypeScript, Vue, React, Solid, etc.
Local dependencies should be installed in package or app where they’re required.
Build process
Section titled “Build process”This is how build command works:
generate-sourcescommand is run, and the source code is generated:vite-awesome-svg-loadersource code is generated:- Packages are added as dependencies.
- Re-exports from packages are added.
- Subpath exports are updated.
all-demospackage is generated. All demos are added as the dependencies to theapps/docspackage.
- All packages are built.
vite-awesome-svg-loaderpackage is built.- All demos are built.
- Apps are built.
Linting
Section titled “Linting”ESLint is used for linting.
Code style
Section titled “Code style”Prettier is used for formatting. All configuration options are set. Formatting that is not covered by Prettier is handled by ESLint.
This project tries to keep the source code clean and readable. Please try to do so as well. For example, don’t nest too many conditions, don’t use bit shifts unnecessarily, etc.
Integrations development
Section titled “Integrations development”- Create an issue to notify the community that you’ll be working on your integration.
- Create an integration package using
npx turbo generate workspacecommand or by copying an existing integration. - Develop integration:
- Open
package.jsonfile inside your integration directory. - Add
"integration-utils": "*"dependency. - Develop your integration.
- Open
- Run
npm run generate-sourcescommand to regeneratevite-awesome-svg-loadersource code. Or just run any build or dev command. - Develop demos for your integration:
- Copy any existing demo and pages in the
/apps/docs/src/content/docsdirectory. - Develop your demos.
- Update the docs:
- Add a glob import for the demos inside the
/apps/docs/src/demosdirectory. - Update the previously copied pages.
- Feel free to add your own pages if needed.
- Add a glob import for the demos inside the
- Copy any existing demo and pages in the
- Submit a PR with your integration.
Loader development
Section titled “Loader development”- Create an issue to notify the community that you’ll be working on your feature.
- Develop your feature. Make sure to document it with JSDoc.
- Update the docs to showcase your feature.
- Test if demos work.
- Submit a PR.
Running docs and demos
Section titled “Running docs and demos”Docs and demos may be run in parallel with live reload by using npm run dev command.
However, this spins up a lot of Vite watchers running simultaneously. If your machine can handle it, it’s fine.
Alternative workflow is recommended:
- Run
npm run build:appscommand to build all packages and demos. - Run
npm run dev:docs:standalonecommand to run documentation website. - After changing the code, run
npm run build:appscommand again. This will rebuild only changed packages. - If multiple packages are rebuilt, Astro server may hang. In this case, kill it and run
npm run dev:docs:standalonecommand again.
Testing
Section titled “Testing”This guide outlines testing principles. For concrete examples, see already existing tests.
The goal of the tests is to verify that the final library’s package is working correctly.
Core principles
Section titled “Core principles”-
Tests should be added as packages inside the
/tests/directory. -
There must be one test suite per package.
-
Tests structure must mirror package’s structure. Multiple test files per one package’s file may be used. In this case, test files must be placed in a folder with the package’s file’s name.
-
In future, demos in the documentation website may also be automatically visually tested.
-
If multiple packages perform the same tests, the tests may be abstracted. The abstraction must be placed in the
testsdirectory. -
While testing is performed on per-package basis, the
vite-awesome-svg-loaderpackage must be used instead of its dependencies.It is reasonable to think that if all dependencies are tested, transitively the compilation of these dependencies is also tested. In practice, a change in
tsconfig.jsonor some Vite plugin may alter the final bundle’s behavior which renders tests invalid. -
Tests must be performed in a real browser for correctness’ sake.
-
If possible, the widest range of modern browsers should be tested.
-
Tests should focus on
vite-awesome-svg-loader, not the frameworks. -
Tests for trivial code may be omitted. For example, there’s no need to test that
2+2equals5. Nevertheless, these tests are welcome if they don’t bring unreasonable maintenance burden.
Tooling
Section titled “Tooling”Each test suite may use its own tooling. However, some recommendations have formed while researching the available software.
The tests must follow chosen tooling’s conventions.
Unit and integration testing. DOM manipulation. Components.
Section titled “Unit and integration testing. DOM manipulation. Components.”Cypress is recommended for testing DOM manipulation and framework components.
Cypress is the only tool that can run tests in the same context as components and supports multiple browsers out of the box. This makes state modification easy and boilerplate-free.
Cypress supports synchronous assertions via Chai and asynchronous assertions (with wait time, retries and other
features) via its own API (cy.get(...).should(...)).
This allows testing both synchronous DOM manipulation and asynchronous framework lifecycle.
e2e testing
Section titled “e2e testing”If testing user’s interactions only is required, Playwright is recommended.
It supports all major browsers and accurately simulates user’s actions (events are fired as the result of user’s interactions, not as a JS script).