reskript

0.26.7 • Public • Published

reSKRipt

基于react与antd技术栈的命令行工具集合。本工具目标整合Lint、Test、Build、Babel、DevServer等一系列功能,使产品线不再重复性地维护复杂的配置文件及相关脚本。

关于数据采集

reskript默认不进行任何数据的采集,如果支持本工具的开发,可以选择打开。在打开采集后,会采集使用过程中的异常信息,异常信息中将包括:

  • 当前操作系统中的用户名。
  • 当前操作系统类型和版本。
  • 异常发生的详细堆栈,可能由于webpack的异常信息,导致包含一部分的源码。
  • 使用reskript的目标系统的名称,取自package.json中的name字段。

可以设置RESKRIPT_TRACK=on来打开采集功能,如:

RESKRIPT_TRACK=on skr build
# 或使用更全局的环境变量 
# export RESKRIPT_TRACK=on 
# skr build 

安装

要求系统安装node >= 8.9.0版本。

npm install --save-dev reskript

在安装后,会增加一个skr命令。修改项目的package.json中的scripts部分来增加相关功能:

"scripts": {
    "lint": "skr lint",
    "test": "skr test",
    "start": "skr dev",
    "build": "skr build",
    "analyze": "npm run build -- --analyze",
}

以上列出了skr命令的常用功能,如果有定制化要求(如使用build.sh代替简单的skr build),则同样可以调用这些命令完成工作。

自动生成配置文件

使用skr satisfy自动在项目中添加需要的配置文件,并安装相关的依赖。

Usage: satisfy [options]

Satisfy project dependencies

Options:
  --ts            whether this is a typescript project
  --type [value]  your package type, either "app" or "lib" (default: "app")
  --ut [value]    environment of unit test, "node" or "react" (default: "node")
  -h, --help      output usage information

初始化会为项目添加以下内容:

  • 添加webpack.config.js用于WebStorm解析路径,注意这个配置文件不用于实际的构建,仅供IDE参考。
  • 添加eslint的配置,指向reskript指定的规则。
  • 根据--ts参数,添加tsconfig.jsonjsconfig.json
  • 根据--webpack参数自动安装webpack的依赖。
  • 如指定--ut=react,则自动安装enzyme

如果已经手工完成以上步骤,则无需运行此命令进行初始化。

检查代码

使用skr lint检查代码规范。

Usage: lint [options] [files...]

Lint files, by default .js(x) files under src and webpack are linted

Options:
  --changed                    lint only changed files in git workspace
  --staged                     lint only staged (both partially and fully) files in git workspace
  --allow-unsafe-react-method  allow UNSAFE_* methods in react component
  --fix                        fix possible lint errors
  -h, --help                   output usage information

对于新项目,建议直接使用skr lint检查整个项目。遗留项目可以使用skr lint --changed仅检查修改过的文件。同时在Git的pre-commit钩子上使用skr lint --staged来保证入库的代码是符合规范的。

测试

使用skr test测试。

Usage: test [options]

Test

Options:
  --cwd [value] override current working directory (default: process.cwd())
  --coverage  indicates test coverage information
  --watch     watch files for changes and rerun tests related to changed files
  --target [value] specify test environment of the project is "react" or "node" (default: "node")
  --changedSince [value] runs tests related to the changes since the provided branch. (default: '')
  -h, --help  output usage information

skr test会自动搜索所有 .test.js 结尾的文件运行,建议的文件结构为

/__tests__
    * util.test.js
util.js

然后在 util.test.js

import {add} from '../util';

describe('add', () => {
    test('1 + 2 = 3', () => {
        expect(add(1, 2)).toBe(3);
    })
})

CHANGE: 0.25.17 之后

  1. 不再支持相对路径的src目录参数,resolve src只是cwd下面的src目录。影响是:只可以在eefe root目录级别运行skr test,才能正确resolve @/ 到 src/ 下面

  2. 添加了根据项目里的jest.config.js来配置jest的能力。

  • 如果项目中有jest.config.js,需要指定reskript/config/jest-react.js的相对路径(根据当前项目)来引入skr test的默认配置。例如:'./node_modules/reskript/config/jest-react.js'。 如果使用require.resolve('reskript/config/jest-react.js'),需要变成相对目录,'./' + path.relative('', require.resolve('reskript/config/jest-react.js')), 前面的 ./ 是需要的。 如果是react,引用jest-react.js,如果是node,引用jest-node.js
  • 如果项目中没有jest.config.js,skr test会用默认配置(与preset相同) 注意: 如果用了jest.config.js,settings下面的test值将不起作用。

实时预览组件

使用skr play可以打开一个实时编辑页面,用于测试及预览指定的组件。

Usage: play [options] <target>

Start a playground to debug a certain component

Options:
  --cwd [value]           override current working directory (default: process.cwd()")
  --build-target [value]  set build target, default to "dev" (default: "dev")
  -h, --help              output usage information

如执行skr play src/components/UserInfo/index.js后,则会进行自动构建,随后可在http://localhost:9999中打开实时预览页面,页面左侧可编辑代码,右侧进行实时的预览。

打包基础库

使用skr rollup来对基础库(非业务系统)进行打包,底层使用rollup实现。

Usage: rollup [options]
 
Build entire app
 
Options:
  --cwd [value]   override current working directory (default: process.cwd())
  --mode [value]  set build mode, default to "production" (default: "production")
  --clean         remove dist directory before build
  -h, --help      output usage information

可以在settings.js中导出rollup对象,允许有以下属性:

  • {Object} namedDependencyExports:指定第三方库的命名导出,具体参考rollup-plugin-commonjs的说明
  • {string} styleOutput:指定样式的输出格式,为"inject"时内置到JavaScript中,为"extract"时输出为与JavaScript同名的.css文件,为"index"时输出为单个style/index.css文件,默认值为"index"
  • {string} target:指定编译的目标平台,为"web""node""universal",默认为"universal"。指定"web"时仅用于浏览器,但可以基于此做一些优化,如移除node模块的依赖。

除此以外,当前版本不暴露任何配置,封闭了eslintbabelpostcss等能力。

构建系统

基础目录结构

构建系统对目录结构有一定要求,必须包含以下部分:

/src
    /styles
        *.global.less # .global.less文件不会经过CSS Modules编译,可放置一些全局的样式
        *.var.less # .var.less会被提取作为LESS编译时的变量,内部仅可声明变量(以及注释)
    /entries
        index.js # 主入口
settings.js # 系统配置文件

其中*.global.less事实上可以放置在任意位置,只要是以.global.less结尾的,均不会经过CSS Modules处理。

默认.less文件内可直接使用EST插件提供的内容,其它相关loader的配置请直接参考源码,不再赘述。

特殊文件命名

以下是可用的一系列特殊处理的文件命名规则:

  • *.global.less:定义全局的样式,不会经过CSS Modules处理。
  • *.worker.js:定义Web Worker,会被编译成一个Worker类。

全局变量

在源码中可以使用以下的全局变量(通过DefinePlugin提供):

  • process.env.XXX:对应环境变量中的值。
  • $features.xxx:对应Feature Matrix中的特性值。
  • $build.mode:构建时的mode值,建议使用这个变量来代替process.env.NODE_ENV
  • $build.version:当前构建的版本号。
  • $build.target:当前构建的目标。
  • $build.time:当前构建的时间,为ISO格式字符串。

以上全局变量可直接使用,不会被lint功能认为错误。

系统配置

对于业务系统,必须在项目根目录下放置一个settings.js,该文件为项目的整体配置,需导出featureMatrixbuilddevServeradditionplugins共五项。基础库也可通过settings.js(可选)导出rollup用于第三方库的构建,但与系统的构建无关,参考前文:

Feature Matrix

除第三方库类型的项目外,要求所有系统使用Feature Matrix维护源码,避免Feature分支开发导致的合入困难问题。

settings.js导出featureMatrix对象,该对象的每一个属性均代表一个Feature集合。

一个项目必须至少包含以下3个Feature集合:

  • stable:用于全流量。
  • insiders:用于小流量。
  • dev:用于开发。

以上3个集合为必须,其中dev仅在开发过程使用。如果系统本身没有灰度机制,可以使用最简单的模板:

exports.featureMatrix = {
    stable: {},
    insiders: {},
    dev: {}
};

构建配置

settings.js导出builld对象,可以包含以下属性:

  • {boolean} thirdParty:是否以第三方库的形式构建,第三方库的构建不使用featureMatrix、不拆分chunk,同时构建产出不带hash、不产出HTML文件。
  • {boolean} reportLintErrors:构建过程中检查代码规范,默认值为true。如无特殊原因,禁止关闭这个开关。
  • {boolean} extractCSS:是否将CSS抽取到独立的.css文件中,默认为true,当CSS的顺序有问题,或者构建第三方库时,可以选择设置为false
  • {Condition} noCompileScripts:无需经过babel编译的JavaScript文件列表,仅包含项目源码部分,不要包含第三方的库。
  • {Condition} noModulesStyles:无需经过CSS Modules处理的样式文件列表,仅包含项目源码部分,不要包含第三方的库。如果整个系统没有使用CSS Modules,则该配置的值可以为[() => true]
  • {string[]} styleResources:用于编译LESS的变量资源文件列表。每个文件均会被注入到所有的LESS文件前面,作为全局可用的资源。
  • {number} largeAssetSize:生成静态文件的限值,以字节为单位。小于该值的会被编译为DataURI内联,大于该值的会变为单独的文件。默认值为8KB
  • {Object} browserSupport:支持的浏览器范围,用于babel-preset-env
  • {boolean} styleName:是否使用styleName来调用CSS Modules,默认为true
  • {boolean} polyfill:是否自动引入core-js的相应polyfill,默认为true。如果你使用了其它方式引入polyfill,设置为false即可。
  • {string} extraLessPaths:LESS中@import的查找路径,默认为src, node_modules, src/styles这三个目录。
  • {string} cssScope:给所有的CSS选择器加上一个作用域,如该属性值为#foo,则header > .navigation会变为#foo header > .navigation
  • {Object[]} copies:需要进行复制的静态文件列表,用于copy-webpack-plugin
  • {string} appTitle:应用的标题,用于生成<title>元素。
  • {string} favicon:favicon的位置。
  • {string[]} excludeFeatures:构建过程中需要排除的Feature名称,默认排除['dev'],其它均会被构建。
  • {boolean} autoRouteSplit:自动根据路由进行code split,具体参考自动路由拆分章节。

调试服务器

settings.js导出devServer对象,可包含以下属性:

  • {number} port:启动的端口。
  • {string[]} apiPrefixes:需要代理的API请求的前缀,如['/rest', '/api']则会将所有/rest/api的请求代理至后端。
  • {string} defaultProxyDomain:默认的后端域名,仅需填写域名部分(如engmapbeta.baidu.com),可以被--proxy-domain参数覆盖。
  • {string} hot:是否启用HMR,可选值为nonesimpleall。使用none时禁用HMR;为simple时开启简单的HMR,仅对样式等资源生效;为all时开启hotOnly配置,并自动打开React的HMR。

入口页配置

构建或调试允许定制入口页,也允许单系统多入口。

系统必须有src/entries这个目录,其下放置所有的入口文件,默认的名称为index。每一个入口对应以下文件:

  • [name].js:入口的启动脚本。
  • [name].ejs:HTML模板,以EJS作为模板格式,如果一个入口不存在对应的.ejs文件,则会使用默认的模板。自定义模板可使用htmlWebpackPlugin.options.buildIdentifier获取构建版本号。
  • [name].config.js:生成入口页面的额外配置,这个文件的module.exports对象会直接传递给html-webpack-plugin,可以定制化页面信息,也可以将额外的数据传递给[name].ejs模板。

例如某个入口页面的<title>希望得到修改,则可以在[name].config.js中这样写:

module.exports = {
    title: '定制化的标题'
};

入口页的模板([name].ejs)或配置文件([name].config.js)修改后,需要手动重启调试,当前版本并不会自动监听这些文件。

额外配置

settings.js导出addition函数,该函数将接受一个构建时的环境对象,并返回一部分webpack配置。

当由addition函数返回的配置中包含module.rules时,自定义的module.rules将完全覆盖默认的配置(不会做任何的合并策略),其它的配置项则会通过webpack-merge与默认的配置合并。

所谓构建时的环境对象,即通过build导出的对象,外加通过命令行提供的参数。通常来说,其中的mode属性是最为重要的。

默认配置

以下为一个常见的默认配置,仅供参考:

exports.featureMatrix = {
    stable: {},
    insiders: {},
    dev: {}
};
 
exports.build = {
    appTitle: 'React App', // 修改为应用的名称
};
 
exports.devServer = {
    port: 8078, // 修改为不与其它应用重复的端口号
    apiPrefixes: ['/api'],
    defaultProxyDomain: '', // 修改为测试环境地址
    uuapCallbackURL: '/',
    presetUsers: [] // 添加模块登录的预置用户
};
 
exports.addition = () => ({});

使用插件

settings.js导出plugins数组,数组中的每一项为一个函数,函数接受settings.js导出的{featureMatrix, build, devServer, addition}对象和当前命令行参数,并返回一个相同的对象。

插件会按顺序被依次调用,最终返回的对象用于各种功能。

构建产物

构建输出到dist目录,所有静态资源放置于dist/assets目录下,入口HTML页面放置于dist目录下。基于Feature Matrix进行构建后,不同Feature集产生的文件也都混合在一起,无需分隔为不同目录。

在Feature Matrix的模式下,线上分流需要按照HTML文件名分流,如主流量分到stable.html上,小流量则分到insiders.html上。而dist/assets目录则不需要设置鉴权,以便Sentry或Firefox等应用在无Cookie的情况下可以成功下载到Source Map。

如果当前系统线上无法基于HTML文件名分流,则参考“启动构建”章节使用--build-target参数进行兼容。

启动构建

使用skr build构建整个系统。

Usage: build [options]

Build entire app

Options:
  --cwd [value]           override current working directory (default: process.cwd())
  --mode [value]          set build mode, default to "production" (default: "production")
  --src [value]           specify the dir containing source files relative to cwd (default: "src")
  --build-target [value]  create index.html according to specific target
  --analyze               enable bundle analysis
  --clean                 remove dist directory before build
  -h, --help              output usage information

默认基于Feature Matrix构建,需要线上的Nginx等服务器配合分流。如果没有这一能力,则需要指定--build-target参数,该参数指定的Feature集合的构建结果会被复制为index.html,以便上线部署时不会出错。

打开调试服务器

使用skr dev启动调试服务器,初次构建完成后会自动打开网页。

Usage: dev [options]

Start dev server for debugging

Options:
  --cwd [value]            override current working directory (default: process.cwd())
  --mode [value]           set build mode, default to "development" (default: "development")
  --src [value]            specify the dir containing source files relative to cwd (default: "src")
  --build-target [value]   set build target, default to "dev" (default: "dev")
  --proxy-domain [domain]  set api proxy domain, only domain part (www.example.com) is required
  -h, --help               output usage information

在调试过程中,会监听settings.js的变更并重启调试服务器,重启后不会自动打开网页。

自动路由拆分

settings.js中的``exports.build.autoRouteSplit属性为true`时,会启用自动路由拆分,该逻辑会找到合适的拆分点,要求需要满足以下条件:

  1. 组件被使用在<TrackRoute components>属性上,如<TrackRoute exact path="/admin" components={AdminPage} />
  2. 对应的组件必须是默认引入的,即import AdminPage from '../AdminPage'的形式。
  3. 必须配合@ecomfe/react-track使用。

在满足以上条件时,如下代码:

import AdminPage from '../AdminPage';
 
<TrackRoute exact path="/admin" component={AdminPage} />

会被编译为:

import {lazy} from 'react';
 
const LazyAdminPage = lazy(() => import('../AdminPage'));
<TrackRoute exact wrapSuspense path="/admin" component={LazyAdminPage} />

以此获得webpack的code split能力。由于lazy后的组件必须搭配Suspense使用,所以依赖@ecomfe/react-trackTrackRoute组件支持(内部自动添加Suspense)。

当前无法保证此功能100%满足场景,开启后请小心测试。

定制化构建

如果默认的构建配置外加settings.js无法满足,或需要在settings.js中的addition部分复用一些默认的配置,则可以使用reskript提供的函数辅助创建loader相关的配置。

复用loader

reskript导出loaders对象,内含了生成常用loader配置的函数,包括:

  • babel({cwd, mode, browserSupport, ui, styleName})
  • css({mode})
  • cssModules({mode})
  • eslint({mode})
  • less({mode, cwd, extraLessVariables, extraLessPaths})
  • postCSS({mode, cssScope, lint}, {external = false} = {})
  • styleResources({cwd})
  • sourceMap()
  • style({mode})
  • img({mode})
  • url({largeAssetSize})
  • typescript({mode})

以上函数的相关配置均参考构建配置的对应字段。

复用规则

如果在复用loader的情况下,还希望复用module.rules的相关规则,reskript导出rules对象,包括:

  • script(env)
  • less(env)
  • css(env)
  • image(env)
  • file(env)
  • typescript(env)

以上函数均需要一个完成的配置对象(env)作为参数,该对象即settings.js中的addition函数接收的参数。

对于需要修改某一个规则的情况,建议在rules的基础上移除需要修改的规则后全部应用,再增加自定义规则。如某个项目需要将.css文件的规则修改,则可以如下配置:

const {omit} = require('lodash');
const {rules} = require('reskript');
 
exports.addition = env => {
    // 先移除css的规则
    const baseRules = Object.values(omit(rules, ['css'])).map(rule => rule(env));
 
    return {
        module: {
            rules: [
                ...baseRules,
                {
                    test: /\.css$/,
                    use: [...]
                }
            ]
        }
    };
};

reskript无法保证每一次升级时在rules对象上保持完全的向后兼容,如上的写法可比较灵活地应对升级导致的规则的增减。

获取webpack配置

为了方便与其它工具如react-styleguidist进行整合,reskript允许通过程序获取webpack的配置。使用createBuildConfig(env)createDevConfig(env)函数分别获取完整构建或者开发调试用的配置对象。

其中env对象必需包含以下属性:

  • {Object} projectSettings:来自settings.js的对象,通常使用require('./settings')获取即可,具体结构见前文描述。
  • {string} mode:构建的形式,为developmentproduction
  • {string} usage:构建使用场景,为build(构建产出结果)或devServer(开发调试服务器)。

其它可选属性参考builddev命令的帮助文档,所有命令行参数均可在camelCase化后作为env对象的属性传入。

辅助排查

skr命令出现不符合预期的问题时,它很有可能是因为间接依赖的第三方包导致的。由于reskript并不使用shrinkwrap机制锁定版本,因此需要导出所有第三方依赖的版本来确定问题。使用skr doctor可以得到排查问题的相关信息:

Usage: doctor [options]

Collect debug information for et itself

Options:
  --cwd [value]  override current working directory
  --json         print result in JSON format
  -h, --help     output usage information

通常使用skr doctor | pbcopy可将结果复制到剪贴板中。

对于新项目,建议直接使用skr lint检查整个项目。遗留项目可以使用skr lint --changed仅检查修改过的文件。同时在Git的pre-commit钩子上使用skr lint --staged来保证入库的代码是符合规范的。

TODO

  • 支持DLL:等autodll-webpack-plugin升级后实现。

Readme

Keywords

none

Package Sidebar

Install

npm i reskript

Weekly Downloads

11

Version

0.26.7

License

MIT

Unpacked Size

315 kB

Total Files

275

Last publish

Collaborators

  • buzheng
  • conwnet
  • huoyuxuan
  • otakustay