English | 简体中文
Webpack loader for Omi Single-File Components
You can use npm install or git clone it.
npm install omil --save-dev
# or
npm install eno-loader --save-dev
Configuration webpack file like this:
module: {
rules: [{
test: /\.omi|eno$/,
use: [{
loader: require.resolve('omil'),
options: {
// Use in development, You should remove in production
sourceMaps: 'both',
// Config babel plugins for async, await and other many features
plugins: [
[
"@babel/plugin-transform-runtime",
{
"absoluteRuntime": false,
"corejs": false,
"helpers": true,
"regenerator": true,
"useESModules": false
}
]
]
}
}],
// Or you can use eno-loader or omil directly
// use: ['eno-loader']
// use: ['omil']
}]
}
omil
is a loader for webpack that allows you to author Omi components in a format called Single-File Components.
A *.omi
file is a custom file format that uses HTML-like syntax to describe a Omi component. Each *.omi
file consists of three types of top-level language blocks: <template>, <script>, and <style>
, and optionally additional custom blocks:
<template lang="html" name="component-name">
<!-- replace render function -->
<header onClick="${this.test}">${this.data.title}</header>
</template>
<script>
import style from './_oHeader.css'
export default class {
static css = style + `p{color:red}` // it will combine scoped css,only support static css = xxx
test(){
console.log('Hello Eno!')
}
install() {
this.data = {
title: 'Omi'
}
}
}
</script>
<style>
/* scoped css */
header {
height: 50px;
background-color: #07c160;
color: white;
text-align: center;
line-height: 50px;
width: 100%;
}
</style>
It also supports JSX, if you want to do that, you only write <template>
without lang="html"
attribute in your component like this:
<template>
<header onClick={this.test}>{this.data.title}</header>
</template>
omil
supports using non-default languages, such as CSS pre-processors and compile-to-HTML template languages, by specifying the lang attribute for a language block. For example, you install node-sass after you can use Sass for the style of your component like this:
<style lang="scss">
$height: 50px;
$color: #07c160;
header {
height: $height;
background-color: $color;
}
</style>
You can also use an ES6 class to define a class component by omil.
<template name="ComponentName">
<p>{this.state.title}</p>
</template>
<script>
export default class {
constructor(props) {
super(props)
this.state.title = "Eno Yao"
}
}
</script>
<style lang="scss">
p {color: #58bc58;}
</style>
A higher-order component (HOC) is an advanced technique in React for reusing component logic. HOCs are not part of the React API. Here's a concrete example.
<template name="ComponentName">
<div>
<p>{this.state.title}</p>
</div>
</template>
<script>
const HOC = (props) => {
return (WraooedComponent) => {
return class HOC extends WeElement {
state = {
name: 'Eno Yao',
...props
}
render() {
return (
<div>
Hello World
<WraooedComponent name={{ ...this.state }} />
</div>
)
}
}
}
}
export default HOC({
age: 18
})(class {
constructor(props) {
super(props)
this.state = {
title: 'Lemon'
}
}
componentDidMount() {
console.log(this)
}
handleChange() {}
})
</script>
<style lang="scss">
/* CSS */
p {
color: #58bc58;
}
</style>
A static type system can help prevent many potential runtime errors, especially as applications grow. You can use Single File Components(SFC)
cooperate with Higher Order Components(HOC)
to get support with TypeScript
<template name="Eno">
<div><p>{this.state.name}</p></div>
</template>
<script>
// TypeScript Support
import EnoType from './EnoType.tsx'
export default EnoType(class {
constructor(props) {
super(props);
this.state = { name: 'abc', age: 18}
}
})
</script>
<style lang="scss">
p { color: #58bc58 };
</style>
Now, you can create EnoType.tsx
in editor which provides TypeScript inference inside SFCs and many other great features.
// EnoType.ts
import React from 'react';
interface EnoTypeProps { }
interface EnoTypeState { name: string }
export default (Component: React.ComponentType) => {
return class EnoType extends React.Component<EnoTypeProps, EnoTypeState> {
constructor(props: EnoTypeProps) {
super(props)
this.state = { name: 'Eno Yao' }
}
render() { return <Component /> }
}
}
There are many cool features provided by omil
:
- Allows using other webpack loaders for each part of a Omi component, for example Sass for
<style lang="scss">
and JSX/HTML for<template lang="html">
and ES5+ for<script type="text/babel">
; - Allows custom blocks in a
.omi
or.eno
file that can have custom loader chains applied to them Here Online Demo; - Treat static assets referenced in
<style>
and<template>
as module dependencies and handle them with webpack loaders (Such as htm, to-string-loader); - Simulate scoped CSS for each component (Use Shadow DOM);
- State-preserving hot-reloading during development.
In a nutshell, the combination of webpack and omil
gives you a modern, flexible and extremely powerful front-end workflow for authoring Omi.js applications.
Eno Yao |
---|
MIT