SkillAgentSearch skills...

Omil

📝Webpack loader for Omi.js React.js and Rax.js components 基于 Omi.js,React.js 和 Rax.js 单文件组件的 Webpack 模块加载器

Install / Use

/learn @Wscats/Omil
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

English | 简体中文

Omil 是什么?

omil是一个 webpack 的 loader,它允许你以一种名为单文件组件(SFCs)的格式撰写 Omi 组件:

<template lang="html" name="component-name">
  <header onClick="${this.test}">${this.data.title}</header>
</template>
<script>
export default class {
  test(){ console.log('Hello Eno!') }
  install() {
    this.data = { title: 'Omi' }
  }
}
</script>
<style>
header { color: #58bc58; }
</style>

Omil 还提供了很多酷炫的特性:

  • 允许为 Omi 组件的每个部分使用其它的 webpack loader,例如在<style>的部分使用 Sass 和在<template>的部分使用 jsx;
  • 允许在一个 .omi 文件中使用自定义块,并对其运用自定义的 loader 链;
  • 使用 webpack loader 将<style><template>中引用的资源当作模块依赖来处理;
  • 在开发过程中使用热重载来保持状态。

简而言之,webpack 和 Omi Loader 的结合为你提供了一个现代、灵活且极其强大的前端工作流,来帮助撰写 Omi.js 应用。

起步

Omi CLI

如果你不想手动设置 webpack,我们推荐使用 Omi CLI 直接创建一个项目的脚手架。通过 Omi CLI 创建的项目会针对多数常见的开发需求进行预先配置,做到开箱即用。

如果Omi CLI提供的内建没有满足你的需求,或者你乐于从零开始创建你自己的 webpack 配置,那么请继续阅读这篇指南。

手动设置

安装

首先先安装好Omil

npm install -D omil

如果你使用的是 Visual Studio Code 进行开发,强烈建议下载 Omi Snippets 扩展,它会提供给你语法高亮,局部编译等功能。您可以在 VSC 扩展界面里面搜索 omi 这个关键词出现Omi Snippets点击安装即可,稍等片刻,当它安装成功后会提醒你需要重新加载编辑工具,点击重新加载即可使用。

<img src="https://wscats.github.io/omi-docs/public/images/omi-snippets.png">

每个Omil包的新版本发布时,一个相应版本的Omi Snippets也会随之发布。

webpack 配置

Omi Loader 的配置和其它的 loader 基本一样。

// webpack.config.js
module.exports = {
  module: {
    rules: [
      // ... 其它规则
      {
        test: /\.omi|eno$/,
        loader: 'omil'
      }
    ]
  }
}

一个更完整的 webpack 配置示例看起来像这样:

module.exports = {
  mode: 'development',
  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']
    }]
  }
}

Omi Snippets

在配置完 Omil 之后,我们可以在 VS Code 上同时安装好 Omi Snippets 扩展,这个插件可以方便的让你把 .omi 和 .eno 后缀文件在未经过 webpack 处理前转化为 .js 文件,让你可以直观了解到单文件组件经过 omil 转化后的 JS 文件内容,这相当于局部编译减轻 webpack 处理单文件时候的不必要消耗。

目录结构

例如你在 webpack 的入口文件夹中有一个 .omi 的后缀文件,当你新建并经过编辑保存之后,Omi Snippets扩展会在同级目录下新建一份同名但不同后缀的 .js 文件

  • src
    • Hello.omi
    • Hello.js

|Hello.omi|开发中你需要编写的单文件组件| |-|-| |Hello.js|修改或者保存文件Hello.omi后经过插件转化的js文件|

如下图,左边的代码是我们编写的 .omi 后缀的单文件组件,右边是经过 Omi Snippets 生成的 .js 后缀文件。

<img src="https://wscats.github.io/omi-docs/public/images/transfer.png" />

示例代码

上图的示例代码如下

  • <template> 标签负责放 JSX 的内容,属性name="my-test"为该组件的名字,后面可以在 JSX 中用<my-text>使用该组件;
  • <script> 标签负责放入组件的逻辑文件,固定的结构为 export default class { // 你的代码 }或者为export default HOC(class { // 你的代码 })两种形式,第一种是定义类组件,第二种用来定义高阶组件,你的代码部分可以放入生命周期,函数等;
  • <style> 标签负责定义该组件的局部样式
<template name="my-test">
  <div class="example">
    { this.data.msg }
  </div>
</template>

<script>
export default class {
  install () {
    this.data = {
      msg: 'Hello world!'
    }
  }
}
</script>

<style>
.example {
  color: red;
}
</style>

以下代码就是经过 Omi Snippets 生成的 .js 后缀文件,可以用于在你没有 omil 模块下,主逻辑文件或者其他组件引入调用。

import { WeElement, define, h } from "omi";
class MyTest extends WeElement {
  render() {
    return h(
      "div",
      {
        class: "example"
      },
      this.data.msg
    );
  }
  install() {
    this.data = {
      msg: "Hello world!"
    };
  }
}
MyTest.css = `
.example {
  color: red;
}
`;
define("my-test", MyTest);

配合 React 开发

安装 React 脚手架和一些必要模块。

npm install create-react-app
# 初始化项目
create-react-app my-project
# 进入项目文件夹目录
cd my-project
# 安装项目依赖
npm install
# 安装 styled-components 这个务必得安装 用于处理 React 单文件组件局部样式
npm install styled-components --save
# 安装 omil 处理React单文件组件,把 .omi 或者 .eno 后缀文件处理为 JS
npm install omil --save-dev

在配置完 Omil 之后,我们可以在 VS Code 上同时安装好 Omi Snippets 扩展,这个插件可以方便的让你把 .omi 和 .eno 后缀文件在未经过 webpack 处理前转化为 .js 文件,让你可以直观了解到单文件组件经过 omil 转化后的 JS 文件内容,这相当于局部编译减轻 webpack 处理单文件时候的不必要消耗。

编写第一个组件

现在你可以使用单文件组件来编写 React 组件,默认生成类组件。

  • name属性值是组件名要满足 React 框架的组件名字定义规范,首字母必须大写字母;
  • <template>模板中不能有<script><style>代码片段。
<template name="Component-name">
    <div>
        <p>{this.state.title}</p>
    </div>
</template>
<script>
export default class {
    constructor(props) {
        super(props)
        this.state = {
            title: "react"
        }
    }
    componentDidMount(){
        console.log('生命周期')
    }
}

</script>
<style>
p {color: #58bc58};
</style>

以上文件经过 Omil 处理后将会转化为以下代码:

import { Component as WeElement, createElement as h } from "react";
import styled from "styled-components";
const StyledComponents = styled.div`
  /* CSS */
  p {
    color: #58bc58;
  }
`;

class ComponentName extends WeElement {
  render() {
    return h(
      StyledComponents,
      null,
      h("div", null, h("p", null, this.state.title))
    );
  }

  constructor(props) {
    super(props);
    this.state = {
      title: "react"
    };
  }

  componentDidMount() {
    console.log("生命周期");
  }
}

ComponentName.css = `
/* CSS */
p {color: #58bc58};
`;
export default ComponentName;

语言块规范

简介

.omi 文件是一个自定义的文件类型,用类 HTML 语法描述一个 Omi 组件。每个 .omi 文件包含三种类型的顶级语言块 <template><script><style>:

<template name="my-test">
  <div class="example">
    { this.data.msg }
  </div>
</template>

<script>
export default class {
  install () {
    this.data = {
      msg: 'Hello world!'
    }
  }
}
</script>

<style>
.example {
  color: red;
}
</style>

Omil 会解析文件,提取每个语言块,如有必要会通过其它 loader 处理,最后将他们组装成一个 ES Module,它的默认导出是一个 Omi.js 组件定义好的自定义标签对象。

Omil 支持使用非默认语言,比如 CSS 预处理器,预编译的 HTML 模版语言,通过设置语言块的 lang 属性。例如,你可以像下面这样使用 Sass 语法编写样式:

<style lang="sass">
  /* write Sass! */
</style>

语言块

<template>模板

每个 .omi 文件最多包含一个 <template> 块。

内容将被提取,如果是 JSX 会编译为函数片段,如果为 html 会编译为字符串,并最终注入到从<script>导出的组件 render 函数中。

属性name = "xxx-xxx"(Omi组件)

定义name="xxx-xxx"可以给组件定义一个名字,这个名字会自动调用 omi 框架的 define('xxx-xxx', xxxXxx) 方法来注册组件,你就可以在页面中用这个属性名<xxx-xxx></xxx-xxx>来使用该组件

注意:

  • name属性值是组件名要满足 omi 框架的组件名字定义规范,首字母不能用大写字母,并且中间必须有-字符;
  • <template>模板中不能有<script><style>代码片段。
<template name="my-test">
  <div class="example">
    { this.data.msg }
  </div>
</template>

在页面容器中如此使用

<my-test/>
<my-test></my-test>

属性name = "XxxXxx"(React组件)

定义name="XxxXxx"可以给组件定义一个名字,这个名字会自动调用 React 框架的 React.Component 方法来定义类组件,你就可以在页面中用这个属性名<XxxXxx></XxxXxx>来使用该组件

注意:

  • name属性值是组件名要满足 React 框架的组件名字定义规范,首字母必须大写字母;
  • <template>模板中不能有<script><style>代码片段。
<template name="MyTest">
  <div class="example">
    { this.data.msg }
  </div>
</template>

在页面容器中如此使用

<MyTest/>
<MyTest></MyTest>

属性lang = "html"(仅支持Omi)

默认情况下,我们的<template>模板是使用 JSX 语法,如果我们增加属性lang = "html",就可以支持编写html格式的字符串模板,你可以使用 ES6 的语法来编写 html 模板<div>${ this.data.msg }<div>,Omil 和 Omi-Snippets 会自动帮你引入Omi.html()方法帮你在客户端进行处理,会有一定的性能损耗,一般情况下不建议使用。

<template name="my-test" lang="html">
  <div class="example">
    ${ this.data.msg }
  </div>
</template>

<script>脚本

每个 .omi 文件最多包含一个 <script> 块。

类组件

如果我们使用过 react 我们会了解到组件通常有两种定义方式,一种是函数组件,一种是类组件,Omil 默认是帮你创建类组件,我们在export default class { // 你的代码 }或者module.exports = class { // 你的代码 }片段中写入你的组件逻辑代码,

注意:

  • 定义类组件必须是export default class { // 你的代码 }这种写法,class MyText {} ; export default MyText这种写法不可以,因为 Omil 和 Omil Snippets 只识别连续的export default class这段字符串

|export default class { // 你的代码 }|可以|建议使用| |-|-|-| |module.exports = class { // 你的代码 }|可以|支持| |class MyText { // 你的代码 }<br/>export default MyText|不可以|不支持| |class MyText { // 你的代码 }<br/>module.export = MyText|不可以|不支持|

<script>
export default class {
  install () {
    this.data = {
      msg: 'Hello world!'
    }
  }
}
</script>

高阶组件(仅支持React)

有时候我们可以使用高阶组件拓展组件本身的一些功能,高阶组件跟类组件一样,只支持下面规定的写法。

|export default HOC(class { // 你的代码 })|可以|建议使用| |-|-|-| |module.exports = HOC(class { // 你的代码 })|可以|支持| |class MyText { // 你的代码 }<br/>export default HOC(MyText)|不可以|不支持| |class MyText { // 你的代码 }<br/>module.export = HOC(MyText)|不可以|不支持|

<script>
export default HOC(class {
  install () {
    this.data = {
      msg: 'Hello world!'
    }
  }
})
</script>

下面是一个高阶组件的详细参考例子

<template name="MyTest">
    <div><p>{this.state.title}</p></div>
</template>
<script>
// 高阶函数
const HOC = (props) => {
    return (WraooedComponent) => {
        return class HOC extends WeElement {
            render() {
                return (<div><WraooedComponent name={{ ...this.props }} /></div>)
            }
        }
    }
}
export default HOC({
    age: 18
})(class {
    install () {
        this.data = {
            msg: 'Hello world!'
        }
    }
})
</script>
<style lang="scss">
p { color: #58bc58; }
</style>

或者你可以这样写

<template name="MyTest">
    {HOC(<div><p>{this.state.title}</p></div>)}
</template>
<script>
// 高阶函数
const HOC = (props) => {
    return (WraooedComponent) => {
        return class HOC extends WeElement {
            render() {
                return (<div><WraooedComponent name={{ ...this.props }} /></div>)
            }
        }
    }
}
export default class {
    install () {
        this.data = {
            msg: 'Hello world!'
        }
    }
}
</script>
<style lang="scss">
p { color: #58bc58;

Related Skills

View on GitHub
GitHub Stars181
CategoryDevelopment
Updated1y ago
Forks2

Languages

JavaScript

Security Score

70/100

Audited on Feb 23, 2025

No findings