Skip to content

Instantly share code, notes, and snippets.

@banyudu
Created March 19, 2020 06:56
Show Gist options
  • Save banyudu/74fc5f646485a528307570c24f73f632 to your computer and use it in GitHub Desktop.
Save banyudu/74fc5f646485a528307570c24f73f632 to your computer and use it in GitHub Desktop.
CI中运行ESLint的优化方法

CI中运行ESLint的痛点

虽然在CI中引入ESLint能极大地帮助代码的规范,但是它也会带来额外的成本。

其中最关键的,就是CI执行过程中的时间消耗了。

一个一般规模的前端工程,执行npm install操作需要几分钟,执行eslint又会需要一两分钟。因此在CI中引入ESLint大致会将CI流程的时间延长好几分钟。如果项目比较大,问题可能会更严重。

正是因为这个原因,很多团队不得不将eslint从流水线中删除。

然而这个问题真的无解吗?其实不然。

优化方案

从上面的分析中能看出,有两处主要的性能优化点。一个是npm install过程,另一个是eslint过程,下面我分别给出它们各自的优化方案。

优化 npm install 过程

大部分时候,npm 依赖的内容是不变的。所以反反复复地安装它,就有些浪费。我们可以通过 Docker cache 和依赖前置来解决这个问题。

假设优化之前的Dockerfile如下

FROM node:alpine-12
WORKDIR /code
ADD . /code
RUN npm install
RUN npx eslint .

因为 ADD . /code这个步骤,每次代码变更时都会重新执行,所以后面的npm install自然就无可用的cache,即每次都需要重新安装。

如果稍微调整一下,将依赖文件前置:

FROM node:alpine-12
WORKDIR /code
COPY package.json package-lock.json /code # 提前复制依赖文件
RUN npm install

ADD . /code
RUN npx eslint .

这样一来,只要 package.json 和 package-lock.json文件的内容没有发生变化,npm install的步骤就可以命中cache直接跳过。

因为在大部分时候,package.json和package-lock.json文件的内容不变,npm install能直接跳过,所以能节省下来几分钟的时间。

优化 eslint 过程

ESLint一般只会花费1~2分钟,但是蚊子再小也是肉,还是有优化空间的。

关闭警告

首先,因为CI中一般只需要检测 eslint error,无需处理 warning。所以可以直接打开 --quiet选项忽略warnings。如果当前代码质量不高,警告比较多的话,打开这个选项能节省不少的处理时间。

然后,还可以利用 eslint cache 来进一步压缩其运行时间。

打开Cache

ESLint运行时,支持设置 --cache 选项和 --cache-location 选项,分别用于启用 eslint cache 和设置eslint cache的存储位置。

为了能够利用 Docker cache,我们需要在多次流水线之间共享存储,Dockerfile需要做一些调整。

  1. 首先,因为 docker build 时还不支持挂载Volume,所以要将 eslint 具体执行操作移动到 CMD 环节中,并在之后运行它。即:

    FROM node:alpine-12
    WORKDIR /code
    COPY package.json package-lock.json /code # 提前复制依赖文件
    RUN npm install
    
    ADD . /code
    CMD npx eslint .
    $ docker build . -t my-eslint-image
    $ docker run my-eslint-image
  2. 然后,设置下共享Volume:

    $ docker build . -t my-eslint-image
    $ docker run -v /tmp/cache:/cache my-eslint-image # 将host上的/tmp/cache映射到容器的 /cache目录
  3. 最后,打开 eslint 的 cache 和 cache-location 选项:

    FROM node:alpine-12
    WORKDIR /code
    COPY package.json package-lock.json /code # 提前复制依赖文件
    RUN npm install
    
    ADD . /code
    CMD npx eslint . --cache --cache-location /cache/.eslintcache

这样就设置好了。每次运行eslint时,它会从 /cache/.eslintcache (对应于host的 /tmp/cache/.eslintcache )中读取cache信息,并在运行结束后更新这个文件。

在这个步骤完成后,每次eslint运行时,只需要处理有变动的文件。时间也会大大缩短。

以上就是我在CI中运行ESLint的经验,希望对你有所帮助!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment