6 KiB
id | title |
---|---|
plugin-theme | Theme Plugin |
What's a theme plugin?
Verdaccio uses by default a custom UI that provides a good set of feature to visualize the packages, but might be case your team needs some custom extra features and here is where a custom theme is an option. The plugin store static assets that will be loaded in the client side when the page is being rendered.
How a theme plugin load phase works?
stateDiagram-v2
state if_loads <<choice>>
state if_load_fails <<choice>>
start : Verdaccio start
Yes: Loading custom plugin
No: Custom plugin not found
Yes_loads: Plugin loads successfully
No_loads: Plugin fails on load
load_default: Load default theme (@verdaccio/theme-ui)
Crash: Verdaccio stops
[*] --> start
start --> if_loads
if_loads --> No: false
if_loads --> Yes : true
Yes --> if_load_fails
No --> load_default
if_load_fails --> No_loads: false
if_load_fails --> Yes_loads : true
No_loads --> Crash
How the assets of the theme loads?
:::caution
By default the application loads on http://localhost:4873
, but in cases where a resverse proxy with custom domain are involved the assets are loaded based on the property __VERDACCIO_BASENAME_UI_OPTIONS.base
and __VERDACCIO_BASENAME_UI_OPTIONS.basename
, thus only one domain configuration can be used.
:::caution
The theme loads only in the client side, the application renders HTML with <script>
tags to render the application, the bundler takes care of load any other assets as svg
, images
or chunks associated with it.
The __VERDACCIO_BASENAME_UI_OPTIONS
object
The window.__VERDACCIO_BASENAME_UI_OPTIONS
is available in the browser global context, the shape is documented is defined by the here at the TemplateUIOptions
types definitions.
// output example
{
"darkMode": false,
"basename": "/",
"base": "https://registry.my.org/",
"primaryColor": "#4b5e40",
"version": "5.20.1",
"pkgManagers": [
"yarn",
"pnpm",
"npm"
],
"login": true,
"logo": "",
"title": "Verdaccio Registry",
"scope": "",
"language": "es-US"
}
Theme Configuration
By default verdaccio loads the @verdaccio/ui-theme
which is bundled in the main package, if you want to load your custom plugin has to be installed where could be found.
$> npm install --global verdaccio-theme-dark
:::caution
The plugin name prefix must start with verdaccio-theme-xxx
, otherwise the plugin will be ignored.
:::caution
You can load only one theme at a time (if more are provided the first one is being selected) and pass through options if you need it.
theme:
dark:
option1: foo
option2: bar
These options will be available
Plugin structure
If you have a custom user interface theme has to follow a specific structure:
{
"name": "verdaccio-theme-xxxx",
"version": "1.0.0",
"description": "my custom user interface",
"main": "index.js",
}
The main file index.js
file should contain the following content.
module.exports = () => {
return {
// location of the static files, webpack output
staticPath: path.join(__dirname, 'static'),
// webpack manifest json file
manifest: require('./static/manifest.json'),
// main manifest files to be loaded
manifestFiles: {
js: ['runtime.js', 'vendors.js', 'main.js'],
},
};
};
If any of the following properties are not available, the plugin won't load, thus follow this structure.
staticPath
: is the absolute/relative location of the statics files, could be any path either withrequire.resolve
or build your self, what's important is inside of the package or any location that the Express.js middleware is able to find, behind the scenes theres.sendFile
is being used.manifest
: A Webpack manifest object.manifestFiles
: A object with one propertyjs
and the array (order matters) of the manifest id to be loaded in the template dynamically.- The
manifestFiles
refers to the main files must be loaded as part of thehtml
scripts in order to load the page, you don't have to include the chunks since are dynamically loaded by the bundler.
Manifest file
Verdaccio requires a manifest object to render the html dynamically, in combination with the manifestFiles
the application understand what to render.
Currently only support
js
but if you also needcss
, we are open to discuss it and further improvements.
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
plugins: [
...
new WebpackManifestPlugin({
// this is optional depends of your implementation
removeKeyHash: true,
}),
...
],
Manifest with other bundlers
There is no feedback with other bundlers being used with theme plugins, but with esbuild
could be possible generate manifests.
Alternatives:
Components UI
:::note
The components UI is an experimental feature can be used since verdccio@5.x, it's open to changes and feedback is welcome.
:::note
Create a new user interface from scratch is big effort, to facilitate the task exist the @verdaccio/ui-components package. The components are based on the React library and Material UI.
The package export parts of the user interface that could be reused:
- React Hooks
- Providers (React Context API)
- Components
- Sections: (Sidebar, Detail, Header, Home Page and Footer)