Brine is a set of tools for creating web components by wrapping applications written in popular frameworks.
It enables developers to write components in their favourite framework and use them in any other project, regardless of what framework is used there.
More on the power of web components here
Currently, brine supports the following frameworks
npm install --save brinejs
brine consists of 2 separate layers and a meta object
react
import { define } from 'brinejs/react'
import App from './App'
define(App, {
emits: ["change"],
attributes: ["text", "header"],
style: `.dummy-style{}`,
tag: 'my-react-app',
})
vue
import {createOptions} from 'brinejs/vue'
import App from './App.vue'
svelte
import {createOptions} from 'brinejs/svelte'
import App from './App.svelte'
solid js
import {createOptions} from 'brinejs/solid'
import App from './App'
Brine contains some helper functions that makes building and bundling simpler.
hot component transplant
Hot component transplant server is a websocket server that allows developers to automatically transplant components during development or debugging.
// build script
import {startHotComponentTransplantServer} from 'brinejs/build'
const hotTransplant = startHotComponentTransplantServer()
const build = () => {
// ... some build code
hotTransplant(['path/to/some/file/that/changed.js'])
}
// in browser
new WebSocket('ws://localhost:8080').onmessage =
async (ev) => {import(ev.data+'?t='+Date.now())}
boilerplate generation
Brine has two code generation methods, 'writeMetaFile' and 'writeIndexFile'. They can be used to generate boilerplate code, specifically the meta object that describes the component.
// Generate meta file
import {writeMetaFile} from '/brine'
await writeMetaFile('App.tsx', 'my') // (filePath, prefix or filename)
// output
// App.meta.ts
export const meta = {
emits: ["my-click"],
attributes: ["count", "text", "obj"],
style: `.dummy-style{}`,
tag: 'my-app',
}
// Generate meta file
import {writeIndexFile} from '/brine'
await writeIndexFile('App.tsx', 'my') // (filePath, prefix or filename)
// output
// index.ts
import { define } from 'brinejs/react'
import App from './SolidApp.js'
define(App, {
emits: [] as string[],
attributes: ["count"] as string[],
style: `.dummy-style{}` as string,
tag: 'my-solid-app' as string,
})
css injection
Most builders produce separate js and css files as build output. Since the styling needs to be in the code, this styling must be injected into the code somehow.
Brine has a helper method that can modify a bundled js file and inject css into it. It also updates and adjusts the source map to match the new content.
import {writeJsMapCssGroup, groupJsMapCssFiles} from '/brine'
const groupedFiles = groupJsMapCssFiles(['./dist/App.js'])
await writeJsMapCssGroup(groupedFiles)
type documentation
Type documentation can be extracted and generated for the components
import {
generateTypes,
writeTypesFile,
writeVsCodeTypes,
writeWebTypes
} from 'brine'
const types = await generateTypes(['src/App.tsx'], 'my')
// json file with serialized typing
await writeTypesFile(types, 'dist')
// vscode.html-custom-data.json (VsCode)
await writeVsCodeTypes(types, 'dist')
// web-types.json (JetBrains, IntelliJ/WebStorm)
await writeWebTypes(types, 'dist', {
name: 'example',
version: '1.0.0',
})
// react wrappers
await writeReactWrappersFile(types, 'dist/wrapper')