diff --git a/packages/eslint-plugin-rax-runtime-miniapp/.eslintrc.js b/packages/eslint-plugin-rax-runtime-miniapp/.eslintrc.js
new file mode 100644
index 00000000..2f33f7a7
--- /dev/null
+++ b/packages/eslint-plugin-rax-runtime-miniapp/.eslintrc.js
@@ -0,0 +1,19 @@
+"use strict";
+
+module.exports = {
+ root: true,
+ extends: [
+ "eslint:recommended",
+ "plugin:eslint-plugin/recommended",
+ "plugin:node/recommended",
+ ],
+ env: {
+ node: true,
+ },
+ overrides: [
+ {
+ files: ["tests/**/*.js"],
+ env: { mocha: true },
+ },
+ ],
+};
diff --git a/packages/eslint-plugin-rax-runtime-miniapp/README.md b/packages/eslint-plugin-rax-runtime-miniapp/README.md
new file mode 100644
index 00000000..de42df3b
--- /dev/null
+++ b/packages/eslint-plugin-rax-runtime-miniapp/README.md
@@ -0,0 +1,48 @@
+# eslint-plugin-rax-runtime-miniapp
+
+rax 运行时 eslint 插件
+
+## Installation
+
+You'll first need to install [ESLint](https://eslint.org/):
+
+```sh
+npm i eslint --save-dev
+```
+
+Next, install `eslint-plugin-rax-runtime-miniapp`:
+
+```sh
+npm install eslint-plugin-rax-runtime-miniapp --save-dev
+```
+
+## Usage
+
+Add `rax-runtime-miniapp` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix:
+
+```json
+{
+ "plugins": [
+ "rax-runtime-miniapp"
+ ]
+}
+```
+
+
+Then configure the rules you want to use under the rules section.
+
+```json
+{
+ "rules": {
+ "rax-runtime-miniapp/rule-name": 2
+ }
+}
+```
+
+## Supported Rules
+
+* no-inline-styles
+
+[no-inline-styles](https://github.com/raxjs/miniapp/tree/master/packages/eslint-plugin-rax-runtime-miniapp/docs/rules/no-inline-styles.md)
+
+
diff --git a/packages/eslint-plugin-rax-runtime-miniapp/docs/rules/no-inline-styles.md b/packages/eslint-plugin-rax-runtime-miniapp/docs/rules/no-inline-styles.md
new file mode 100644
index 00000000..57af1f82
--- /dev/null
+++ b/packages/eslint-plugin-rax-runtime-miniapp/docs/rules/no-inline-styles.md
@@ -0,0 +1,34 @@
+# 不推荐使用内联样式 (no-inline-style)
+
+在运行时小程序中,内联样式会导致 `setData` 传输的数据体积变大。本规则会检测元素的内联样式,当内联样式的每一项属性或属性值均为变量时,不会报错。
+
+## Rule Details
+
+
+Examples of **incorrect** code for this rule:
+
+```js
+function Hello() {
+ return (
+ Hello
+ );
+}
+```
+
+```js
+function Hello(props) {
+ return (
+ Hello
+ );
+}
+```
+
+Examples of **correct** code for this rule:
+
+```js
+function Hello(props) {
+ return (
+ Hello
+ );
+}
+```
diff --git a/packages/eslint-plugin-rax-runtime-miniapp/package.json b/packages/eslint-plugin-rax-runtime-miniapp/package.json
new file mode 100644
index 00000000..70210397
--- /dev/null
+++ b/packages/eslint-plugin-rax-runtime-miniapp/package.json
@@ -0,0 +1,32 @@
+{
+ "name": "eslint-plugin-rax-runtime-miniapp",
+ "version": "1.0.0",
+ "description": "rax 运行时 eslint 插件",
+ "keywords": [
+ "eslint",
+ "eslintplugin",
+ "eslint-plugin"
+ ],
+ "author": "chenrongyan",
+ "main": "src/index.js",
+ "scripts": {
+ "lint": "eslint .",
+ "test": "mocha tests --recursive"
+ },
+ "dependencies": {
+ "requireindex": "^1.1.0"
+ },
+ "devDependencies": {
+ "eslint": "^7.1.0",
+ "eslint-plugin-eslint-plugin": "^3.2.0",
+ "eslint-plugin-node": "^11.0.0",
+ "mocha": "^9.0.0"
+ },
+ "engines": {
+ "node": "12.x || 14.x || >= 16"
+ },
+ "peerDependencies": {
+ "eslint": ">=6"
+ },
+ "license": "ISC"
+}
diff --git a/packages/eslint-plugin-rax-runtime-miniapp/src/index.js b/packages/eslint-plugin-rax-runtime-miniapp/src/index.js
new file mode 100644
index 00000000..6f4d9e62
--- /dev/null
+++ b/packages/eslint-plugin-rax-runtime-miniapp/src/index.js
@@ -0,0 +1,10 @@
+/**
+ * @fileoverview rax 运行时 eslint 插件
+ * @author chenrongyan
+ */
+"use strict";
+
+const requireIndex = require("requireindex");
+
+// import all rules in src/rules
+module.exports.rules = requireIndex(__dirname + "/rules");
diff --git a/packages/eslint-plugin-rax-runtime-miniapp/src/rules/no-inline-styles.js b/packages/eslint-plugin-rax-runtime-miniapp/src/rules/no-inline-styles.js
new file mode 100644
index 00000000..0827995b
--- /dev/null
+++ b/packages/eslint-plugin-rax-runtime-miniapp/src/rules/no-inline-styles.js
@@ -0,0 +1,56 @@
+/**
+ * @fileoverview 不推荐使用内联样式
+ * @author chenrongyan
+ */
+"use strict";
+
+const styleSheet = require('../utils/stylesheet');
+const docUrl = require('../utils/docUrl');
+
+const util = require('util');
+
+const { StyleSheets } = styleSheet;
+const { astHelpers } = styleSheet;
+
+module.exports = {
+ meta: {
+ type: 'suggestion',
+ docs: {
+ description: "Using inline styles in runtime miniapp is not recommended",
+ recommended: false,
+ url: docUrl('no-inline-styles')
+ },
+ fixable: null,
+ schema: [],
+ },
+
+ create(context) {
+ const styleSheets = new StyleSheets();
+
+ function reportInlineStyles(inlineStyles) {
+ if (inlineStyles) {
+ inlineStyles.forEach((style) => {
+ if (style) {
+ const expression = util.inspect(style.expression);
+ context.report({
+ node: style.node,
+ message: 'Inline style: {{ expression }}',
+ data: { expression },
+ });
+ }
+ });
+ }
+ }
+
+ return {
+ JSXAttribute: (node) => {
+ if (astHelpers.isStyleAttribute(node)) {
+ const styles = astHelpers.collectStyleObjectExpressions(node.value, context);
+ styleSheets.addObjectExpressions(styles);
+ }
+ },
+
+ 'Program:exit': () => reportInlineStyles(styleSheets.getObjectExpressions()),
+ }
+ }
+};
diff --git a/packages/eslint-plugin-rax-runtime-miniapp/src/utils/docUrl.js b/packages/eslint-plugin-rax-runtime-miniapp/src/utils/docUrl.js
new file mode 100644
index 00000000..9c4f5a88
--- /dev/null
+++ b/packages/eslint-plugin-rax-runtime-miniapp/src/utils/docUrl.js
@@ -0,0 +1,7 @@
+/**
+ * 返回用户可查看的 doc url
+ */
+module.exports = function docUrl(docName) {
+ const repoUrl = 'https://github.com/raxjs/miniapp/tree/master/packages/eslint-plugin-rax-runtime-miniapp';
+ return `${repoUrl}/docs/rules/${docName}.md`;
+}
diff --git a/packages/eslint-plugin-rax-runtime-miniapp/src/utils/stylesheet.js b/packages/eslint-plugin-rax-runtime-miniapp/src/utils/stylesheet.js
new file mode 100644
index 00000000..0c4e8f77
--- /dev/null
+++ b/packages/eslint-plugin-rax-runtime-miniapp/src/utils/stylesheet.js
@@ -0,0 +1,138 @@
+'use strict';
+
+/**
+ * StyleSheets represents the StyleSheets found in the source code.
+ * @constructor
+ */
+function StyleSheets() {
+ this.styleSheets = {};
+}
+
+/**
+ * AddObjectexpressions adds an array of expressions to the ObjectExpressions collection
+ * @param {Array} expressions - an array of expressions containing ObjectExpressions in
+ * inline styles
+ */
+StyleSheets.prototype.addObjectExpressions = function (expressions) {
+ if (!this.objectExpressions) {
+ this.objectExpressions = [];
+ }
+ this.objectExpressions = this.objectExpressions.concat(expressions);
+};
+
+/**
+ * GetObjectExpressions returns an array of collected object expressiosn used in inline styles
+ * @returns {Array}
+ */
+StyleSheets.prototype.getObjectExpressions = function () {
+ return this.objectExpressions;
+};
+
+let currentContent;
+const getSourceCode = (node) => currentContent
+ .getSourceCode(node)
+ .getText(node);
+
+const astHelpers = {
+ isStyleAttribute: function (node) {
+ return Boolean(
+ node.type === 'JSXAttribute'
+ && node.name
+ && node.name.name
+ && node.name.name.toLowerCase().includes('style')
+ );
+ },
+
+ hasArrayOfStyleReferences: function (node) {
+ return node && Boolean(
+ node.type === 'JSXExpressionContainer'
+ && node.expression
+ && node.expression.type === 'ArrayExpression'
+ );
+ },
+
+ collectStyleObjectExpressions: function (node, context) {
+ currentContent = context;
+ if (astHelpers.hasArrayOfStyleReferences(node)) {
+ const styleReferenceContainers = node
+ .expression
+ .elements;
+
+ return astHelpers.collectStyleObjectExpressionFromContainers(
+ styleReferenceContainers
+ );
+ } if (node && node.expression) {
+ return astHelpers.getStyleObjectExpressionFromNode(node.expression);
+ }
+
+ return [];
+ },
+
+ collectStyleObjectExpressionFromContainers: function (nodes) {
+ let objectExpressions = [];
+ nodes.forEach((node) => {
+ objectExpressions = objectExpressions
+ .concat(astHelpers.getStyleObjectExpressionFromNode(node));
+ });
+
+ return objectExpressions;
+ },
+
+ getStyleObjectFromExpression: function (node) {
+ const obj = {};
+ let invalid = false;
+ if (node.properties && node.properties.length) {
+ node.properties.forEach((p) => {
+ if (!p.value || !p.key) {
+ return;
+ }
+ if (p.value.type === 'Literal') {
+ invalid = true;
+ obj[p.key.name] = p.value.value;
+ } else if (p.value.type === 'ConditionalExpression') {
+ const innerNode = p.value;
+ if (innerNode.consequent.type === 'Literal' || innerNode.alternate.type === 'Literal') {
+ invalid = true;
+ obj[p.key.name] = getSourceCode(innerNode);
+ }
+ } else if (p.value.type === 'UnaryExpression' && p.value.operator === '-' && p.value.argument.type === 'Literal') {
+ invalid = true;
+ obj[p.key.name] = -1 * p.value.argument.value;
+ } else if (p.value.type === 'UnaryExpression' && p.value.operator === '+' && p.value.argument.type === 'Literal') {
+ invalid = true;
+ obj[p.key.name] = p.value.argument.value;
+ }
+ });
+ }
+ return invalid ? { expression: obj, node: node } : undefined;
+ },
+
+ getStyleObjectExpressionFromNode: function (node) {
+ let leftStyleObjectExpression;
+ let rightStyleObjectExpression;
+
+ if (!node) {
+ return [];
+ }
+
+ if (node.type === 'ObjectExpression') {
+ return [astHelpers.getStyleObjectFromExpression(node)];
+ }
+
+ switch (node.type) {
+ case 'LogicalExpression':
+ leftStyleObjectExpression = astHelpers.getStyleObjectExpressionFromNode(node.left);
+ rightStyleObjectExpression = astHelpers.getStyleObjectExpressionFromNode(node.right);
+ return [].concat(leftStyleObjectExpression).concat(rightStyleObjectExpression);
+ case 'ConditionalExpression':
+ leftStyleObjectExpression = astHelpers.getStyleObjectExpressionFromNode(node.consequent);
+ rightStyleObjectExpression = astHelpers.getStyleObjectExpressionFromNode(node.alternate);
+ return [].concat(leftStyleObjectExpression).concat(rightStyleObjectExpression);
+ default:
+ return [];
+ }
+ },
+}
+
+module.exports.astHelpers = astHelpers;
+module.exports.StyleSheets = StyleSheets;
\ No newline at end of file
diff --git a/packages/eslint-plugin-rax-runtime-miniapp/tests/src/rules/no-inline-style.js b/packages/eslint-plugin-rax-runtime-miniapp/tests/src/rules/no-inline-style.js
new file mode 100644
index 00000000..2c96f75f
--- /dev/null
+++ b/packages/eslint-plugin-rax-runtime-miniapp/tests/src/rules/no-inline-style.js
@@ -0,0 +1,58 @@
+/**
+ * @fileoverview 不推荐使用内联样式
+ * @author chenrongyan
+ */
+"use strict";
+
+const rule = require("../../../src/rules/no-inline-styles"),
+ RuleTester = require("eslint").RuleTester;
+
+const ruleTester = new RuleTester({
+ parserOptions: {
+ ecmaVersion: 10,
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
+});
+
+ruleTester.run("no-inline-style", rule, {
+ valid: [
+ `function Hello() {
+ return (
+ Hello
+ );
+ }`,
+ `function Hello(props) {
+ return (
+ Hello
+ );
+ }`
+ ],
+
+ invalid: [
+ {
+ code: `
+ function Hello() {
+ return (
+ Hello
+ );
+ }
+ `,
+ errors: [{
+ message: 'Inline style: { backgroundColor: \'#fff\' }'
+ }],
+ }, {
+ code: `
+ function Hello(props) {
+ return (
+ Hello
+ );
+ }
+ `,
+ errors: [{
+ message: 'Inline style: { backgroundColor: \'#fff\' }'
+ }]
+ }
+ ],
+});