The development of omi-component-template is to enable @OMIU developers to learn omi component development faster and more efficiently, and to help developers understand the overall process of OMI component development. Can be used to unify code styles with code specifications.

The OMi-component-Template uses the next generation front-end development and build tool Vite to develop specific component development templates for @OMIU components in combination with the previously developed Omi-Vite scaffolding, which can be combined with the OMI cli.

Original components are packaged and configured to migrate

The main task of omi-component-template development is to migrate the original @omiu/ Button components to the Vite environment, so the packaging build process needs to be modified accordingly. The production side packaging of Vite is packaged using rollup, so you need to migrate the original rollup.config.js to rollupOptions in the new project, viet.config.js

The rollup package is easy to migrate, and Ctrl CV is not a no-go, because Vite already has a lot of plug-ins built in, so we need to simplify the configuration first.

We can find the awesome-vite plugin we need to remove, as well as the parts of the vite built-in plugin we need to remove

Plug-ins included in Vite

  • Rollup /plugin-alias – Defines and resolves aliases for bundled dependencies.
  • Rollup /plugin-commonjs – Convert commonJS modules to ES6.
  • Rollup /plugin-dynamic-import-vars – Resolves dynamic import of containing variables.
  • @rollup/plugin-json-.jsonFiles are converted to ES6 modules.

Plug-ins that are overridden by default in Vite

  • Rollup /plugin-babel – Compile files with Babel.
  • Rollup /plugin-buble – Build ES2015 with Buble.
  • Rollup /plugin-data-uri – Import modules from the URI.
  • @rollup/plugin-html – Create HTML files to serve Rollup bundles.
  • Rollup /plugin-node-resolve – Find and bind third-party dependencies in node_modules.
  • Rollup /plugin-sucrase – Use sucrase to compile TypeScript, Flow, JSX, etc
  • Rollup /plugin-typescript – Integrate rollup and typescript
  • Rollup /plugin-wasm – Support for importing WebAssembly.
  • Rollup /plugin-url – Import file data as URI or ES module.

Actual migration process

The original rollup. Config. Js

import nodeResolve from "rollup-plugin-node-resolve";

import typescript from 'rollup-plugin-typescript';
import scss from 'rollup-plugin-scss'
import commonjs from '@rollup/plugin-commonjs';
const fs = require('fs')
const license = require("rollup-plugin-license");
const pkg = require(".. /package.json");
const licensePlugin = license({
  banner: `${pkg.name} v${pkg.version} http://omijs.org\r\nFront End Cross-Frameworks Framework.\r\nBy dntzhang https://github.com/dntzhang \r\n Github: https://github.com/Tencent/omi\r\n MIT Licensed.`
});

export default {
  input: "src/index.tsx".output: {
    format: "es".file: "./src/index.esm.js".name: pkg.name,
    sourcemap: true.strict: true
  },
  plugins: [
    nodeResolve({
    	main: true
    }),
    scss({
      //output: false,
      output: function (styles, styleNodes) {
        fs.writeFileSync('./src/index.css', styles)
      },
    }),
    typescript(),
    commonjs(),

    licensePlugin
  ],
  external: ['omi']};Copy the code

As you can see from the official Vite documentation and awesome-Vite above, there is no need for manual configuration after migration. Vite is basically built in by default

import nodeResolve from "rollup-plugin-node-resolve";
import typescript from 'rollup-plugin-typescript';
import scss from 'rollup-plugin-scss'
import commonjs from '@rollup/plugin-commonjs';
Copy the code

Therefore, we need to deal with the licensePlugin part. After searching that vite and rollup-plugin-license plug-in are not compatible at present, we searched again in the community to see if there is anything that can replace it. Therefore, I found the viet-plugin-banner plug-in to solve the problem of automatic insertion of banner packaging. After testing and simple reading of the plug-in source code, I found that it can basically meet the requirements of use.

Omi component testing process based on WebComponent

In the early stage, I referred to the unit test process of React and Vue component library. Due to some incompatibility in the ecological part, I changed my thinking to look at the technical ecology based on WebComponent, and wanted to see whether there were relevant component tests or other things. The relevant ecology was found in Lit, a new generation of WebComponent frameworks from Google. Webcomponent itself is supposed to be framework-independent, So I tried to use the technology stack of @web/test-runner + @open-WC /testing.

Installing test tools

npm i -D @open-wc/testing@next
Copy the code

The solution basically uses the fixture provided by @open-WC /testing, and the HTML module renders the WebComponent, Chai is used for assertions, and expect is used to determine whether the product conforms to expectations (CSS Style, Attribute Props, etc.)

import { html, fixture, expect } from '@open-wc/testing'

import '.. /src/index.esm.js'

const defaultProps = {
  plain: false.round: false.circle: false.loading: false.disabled: false.autofocus: false.nativeType: 'button'.block: false,
}

describe('Testing o-button'.() = > {
  it('tests button with default props'.async() = > {const el = await fixture(html` <o-button>Default</o-button> `)
    const button = el.shadowRoot.querySelector('button')
    const classList = button.getAttribute('class').split(' ')
    expect(classList.includes('o-button')).to.be.true
  })

  it('tests setting type'.async() = > {const el = await fixture(html`
      <o-button type="primary">Primary</o-button>
    `)
    const button = el.shadowRoot.querySelector('button')
    const classList = button.getAttribute('class').split(' ')
    expect(classList.includes('o-button-primary')).to.be.true
  })

  it('tests setting disabled'.async() = > {const el = await fixture(html` <o-button disabled>Disabled</o-button> `)
    const button = el.shadowRoot.querySelector('button')
    const classList = button.getAttribute('class').split(' ')
    expect(button.getAttribute('disabled')).to.equal(' ')
    expect(classList.includes('is-disabled')).to.be.true
  })

  it('tests setting plain'.async() = > {const el = await fixture(html` <o-button plain>Plain</o-button> `)
    const button = el.shadowRoot.querySelector('button')
    const classList = button.getAttribute('class').split(' ')
    expect(classList.includes('is-plain')).to.be.true
  })

  it('tests setting size'.async() = > {const el = await fixture(html` <o-button size="medium">Medium</o-button> `)
    const button = el.shadowRoot.querySelector('button')
    const classList = button.getAttribute('class').split(' ')
    expect(classList.includes('o-button-medium')).to.be.true
  })

  it('tests setting round'.async() = > {const el = await fixture(html` <o-button round>Round</o-button> `)
    const button = el.shadowRoot.querySelector('button')
    const classList = button.getAttribute('class').split(' ')
    expect(classList.includes('is-round')).to.be.true
  })

  it('tests setting circle'.async() = > {const el = await fixture(html` <o-button circle>Circle</o-button> `)
    const button = el.shadowRoot.querySelector('button')
    const classList = button.getAttribute('class').split(' ')
    expect(classList.includes('is-circle')).to.be.true
  })

  it('tests setting block'.async() = > {const el = await fixture(html` <o-button block>Block</o-button> `)
    const button = el.shadowRoot.querySelector('button')
    const classList = button.getAttribute('class').split(' ')
    expect(classList.includes('is-block')).to.be.true
  })

  it('tests setting loading'.async() = > {const el = await fixture(html` <o-button loading>Loading</o-button> `)
    const svg = el.shadowRoot.querySelector('svg')
    expect(svg).to.not.be.null
  })

  it('passes the a11y audit'.async() = > {const el = await fixture(html` <o-button></o-button> `)
    expect(el).shadowDom.to.be.accessible()
  })
})

Copy the code