Shinkom, the high-speed rail for real-time cross-browser compatibility analysis for websites.
A JavaScript library powered by a Rust/WASM engine, providing native speed cross-browser compatibility data processing and analysis.
Shinkom is a JavaScript library for real-time website cross-browser compatibility analysis.
It is compatible with many popular libraries and frameworks such as React, Vue, NextJs, Nuxt and Vanilla JS. It is also accessible in Node.Js, see more on Node.Js usage here.
The web has evolved a lot and so have browsers. Among the most popular browsers such as Chrome, Firefox, Edge, Safari, Opera and the like, there are always new browsers being developed aiming to push the boundaries of what is capable of existing browser technology. However, this causes a discrepency in the feature-set between modern browsers since they may use differing technology and architecture when developing new browsers. Web technology and languages such as HTML, CSS and JavaScript are constantly evolving which aids in the problem of features either being widely supported or having limited support between browsers.
This makes cross-browser compatibility all the more important for a web developer to consider as neglecting this could lead to users on other browsers having a poor experience visiting a website due to broken layouts, styling or functionality. However, testing for compatibility on different browsers can often become tedious due to the volume of different browsers and the many versions of each single one.
This is where Shinkom connects the rails!
The purpose of this library is to provide web developers an intuitive library for analysing the compatibility of a website in real-time during development. This project depends heavily on the @mdn/browser-compat-data project by MDN, which stores a large amount of compatibility data about browsers and web features.
Most online browser compatibility websites usually require payment for the use of their services and don't often allow for finer control of what specifically to test within the website. Shinkom aims to provide that fine level of control, to allow web developers to discover the compatibility of their components across many browsers during development.
This library can also make it easier to identify which specific browsers to test immediately without having to sift through documentation to check if a feature works on a particular browser or test the website on every browser to discover potential issues.
Shinkom conducts the analysis of the website content and browser compatibility data and delivers the compatibility result as fast as a bullet train.
It is important to mention that this project is made with WebAssembly through wasm-bindgen.
Therefore, the engine will need to be initialized asynchronously and your server will need to accept the application/wasm MIME type.
It is recommended to read relevant documentation in whichever framework or bundler you are using to apply the correct configuration to accept
WASM files on your server or visit the examples directory, if your framework or bundler of choice is listed there for a working example.
The core engine of Shinkom can be run in Node.js environments, but this is not true for the UI components and the Shinkom entry-point as they are browser-only.
If using a framework that uses SSR, make sure to initialize the library in hooks that perform side-effects (i.e. useEffect or onMounted) to prevent
window is undefined errors during SSR pre-rendering.
Shinkom can be installed from npm via the shinkom package
npm install -D shinkomOnce installed, you can then import the Shinkom package in JavaScript. Shinkom can be used in frontend frameworks, bundlers and vanilla JS.
import { Shinkom } from 'shinkom'
const shinkom = new Shinkom()
shinkom.init()import React, { useEffect } from 'react'
import { Shinkom } from 'shinkom'
export default function App() {
useEffect(() => {
const shinkom = new Shinkom()
shinkom.init()
return () => shinkom.destroy()
}, [])
}<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue'
import { Shinkom } from 'shinkom'
import wasm from 'shinkom/wasm?url'
const shinkom = new Shinkom({
engine: {
wasmURL: wasm
}
})
onMounted(() => {
shinkom.init()
})
onUnmounted(() => {
shinkom.destroy()
})
</script>You can also use Shinkom through the require statement in commonJS.
const Shinkom = require('shinkom').Shinkom
const shinkom = new Shinkom()
shinkom.init()If there are other frameworks or bundlers not listed here as being supported that you would like to use Shinkom with, then consider contributing by creating a pull request on the dev branch to support it and make sure to create an example for others!
shinkom-demo.mp4
The simplest and recommended way to utilize Shinkom is through the main entry-point.
import { Shinkom } from 'shinkom'
const shinkom = new Shinkom()
shinkom.init()This enables the use of the interactive UI and Rust/WASM engine in order to inspect elements on a page.
Shinkom was made to be modular, meaning you can also choose to use individual modules that you would like to make use of for finer control.
import { ShinkomBus, ShinkomState, SKEngine, CompatInspector, CompatUI } from 'shinkom'
const bus = new ShinkomBus()
const state = new ShinkomState()
const engine = new SKEngine(bus)
const inspector = new CompatInspector(bus, state)
const ui = new CompatUI(bus, state, [inspector])
ui.init()
engine.initEngine()The Rust/WASM engine can be used separately from the UI components in cases where you may want to automate compatibility inspection without manually having to interact with a page.
import { SKEngine } from 'shinkom/engine'
const engine = new SKEngine()
const run = async () => {
await engine.initEngine()
}
await run()If needed, you can also preload the WASM file for lazy initialization of the engine, this can be particularly useful when using the engine in SSR applications to eliminate constant cold starts.
import { SKEngine } from 'shinkom/engine'
const engine = new SKEngine()
const preLoad = async () => {
await engine.loadWasm()
}
await preLoad()
// other operations //
await engine.initEngine()In order to discover potential compatibility issues, Shinkom implements a score metric for the result of the compatibility check.
The general schema that an average compatibility check will follow goes like this:
{
"lookup_results": [
// results for each web feature
{
"name": "fake-element", // name of the web feature
"mdn_url": "https://developer.mozilla.org/docs/web/HTML/Reference/Elements/fake-element", // link that leads to MDN documentation of the web feature
"compat_score": "100.00", // score based on the sum of the browser_score and status_score over the max compat score
"browser_score": "100.00", // score based on the sum of weighted scores in each browser
"status_score": "100.00", // score based on the status object in compatibility data
"browsers": [
// results for each checked browser
{
"browser_name": "edge", // name of the browser
"score": {
"raw_score": "100.00", // score based on the safety of feature in browser
"weighted_score": "5.74", // score based on the usage of edge over the total market share between checked browsers
},
"versions": {
"version_added": "34" // feature added in edge engine version 34
}
}
]
}
],
// the overall score of the compatibility check
"overall_score": 100
}This object consists of the following:
- The
overall_scoreproperty is a number that represents the final score of the compatibility check. It is a sum of eachcompat_scorea web feature has been given. - The
lookup_resultsproperty is an array of objects that contains each web feature's individual compatibility results. - The
nameproperty is a string representing the name of the web feature. - The
mdn_urlproperty is a string containing a link to the MDN Web Docs documentation for the web feature. - The
compat_scoreproperty is a string representing the calculated score for the web feature. It is calculated by summing thebrowser_scoreandstatus_scoreand then dividing that sum by the total compatibility score a feature can get (currently 200). - The
browser_scoreproperty is a string representing the sum of theweighted_score's between each browser for the web feature. - The
status_scoreproperty is a string representing the calculated score based on the current status of this web feature (standard_track, experimental, or deprecated). - The
browsersproperty is an array of objects that contains each browsers individual compatibility results. - The
browser_nameproperty is a string representing the name of the checked browser. - The
scoreproperty is an object containing theraw_scoreandweighted_scorefor the web feature in a particular browser.raw_scoreis the calculated score before weighting is applied, which can be interpreted as the safety of a web feature.weighted_scoreis the raw score but with a weighting multiplier calculated as such: total_browser_usage / market_share.
- The
versionsproperty can be either an object or an array of objects depending on whether the web feature has been added, removed or partially implemented in many different versions or just one version.
The scoring for the compatibility check is an important feature to make sure that it gives fair and understandable results that won't leave you guessing why a check resulted in a particular score.
The table below lists the score types and their respective formulas:
| Score Type | Formula |
|---|---|
| overall_score | (compat_score |
| compat_score | ((browser_score + status_score) / MAX_COMPAT_SCORE) * 100 |
| browser_score | ((weighted_score |
| status_score | (status_score / MAX_STATUS_SCORE) * 100 |
| raw_score | Raw score calculation explained below |
| weighted_score | raw_score * (total_usage / market_share) |
Here are a few things to clarify about these formulas:
- In
overall_score, N represents the number of lookup results returned. MAX_COMPAT_SCOREhas a value of 200, whereasMAX_BROWSER_SCOREandMAX_STATUS_SCOREhave a value of 100.- The
raw_scoreis calculated based on many different factors.- If the current version of the browser is greater than the
version_addedvalue, the score is 100. This is also the case ifversion_addedis set totrue. - If the
version_removedvalue is greater than theversion_addedvalue, the score is 0 since it is a removed feature. - If the
partial_implementationvalue is set to true, the score is 80.
- If the current version of the browser is greater than the
total_usageis the usage of a browser across all of its versions, and themarket_shareis the sum oftotal_usagebetween every browser.- The
browser_scoreis the sum of the weighted scores from each browser divided by theMAX_BROWSER_SCORE.
Shinkom can be utilised in Node environments through its Engine module. The UI components are strictly for browser environments, however the engine itself can be used independently in both environments.
import { SKEngine } from 'shinkom/engine'
const skEngine = new SKEngine()
await skEngine.initEngine()
skEngine.checkElement(`<div id="test-div" class="test-classes">Test Div</div>`)const SKEngine = require('shinkom/engine').SKEngine
const skEngine = new SKEngine()
const run = async () => {
await skEngine.initEngine()
skEngine.checkElement(`<div id="test-div" class="test-classes">Test Div</div>`)
}
run()In order to contribute to this project, there are a few prerequisites before doing so:
-
Install the latest stable version of Rust on the official Rust website
-
Install
wasm-packvia this command:cargo install wasm-pack
After that, make sure to run npm i to install project dependencies, create a branch from the dev branch, add your code,
and create a pull request to the dev branch.
After review and approval of the pull request, we can introduce your changes to the dev branch and eventually to the main branch.
When cloning or forking this library, refer to this table in regards to the NPM scripts:
| Scripts | Actions |
|---|---|
| dev:nobuild | Runs Vite dev server without running build:wasm |
| dev | Runs Vite dev server and builds a new WASM files through build:wasm. |
| build | Builds the WASM and JS through build:wasm and build:js and outputs files to dist folder. |
| build:js | Builds the ESM bundles and CJS modules for the Javascript library. |
| build:wasm | Builds the WASM files through wasm-pack and outputs files to a pkg directory. |
| test | Runs tests through Vitest. |
| type:check | Runs tsc to check types in the src directory. |
| gen:data | Generates JSON files for compatibility data and usage data and outputs them to the gen directory. |
This project wouldn't be possible without amazing projects providing the data necessary to perform these compatibility checks.
The browser-compat-data project by MDN is the single reason why this project was made possible. Make sure to check out their project as it compiles a large majority of modern web features across multiple different browser environments.
The caniuse-db package also plays a big role in keeping up-to-date with the global usage data of browsers and their market share.
Make sure to check out both of these great projects!
- Cross-browser compatibility based on MDN's browser-compat-data package
- Configurable cross-browser compatibility DOM inspection
- Full page cross-browser compatibility scan
- HTML parsing and compatibility checks via Rust and WASM engine module
- Interactive side panel for viewing results of compatibility checks
- Hints for improving cross-browser compatibility based on checks
- Optional accessibility evaluation and hints based on WCAG guidelines
- CSS and Javascript file parsing and cross-browser compatibility checks
