likes
comments
collection
share

框架搭建&持续集成(二)

作者站长头像
站长
· 阅读数 68

之前每次测试都需要使用parcel运行项目,打开浏览器和控制台,这样太麻烦了!

能不能只输入一行命令(自动打开浏览器,自动刷新),就能知道代码有没有问题?==>使用自动化测试

一、使用Karma做自动化测试

工具介绍

  1. Karma([ˈkɑrmə] 卡玛)是一个测试运行器,它可以自动呼起浏览器,自动加载测试脚本,然后自动运行测试用例
  2. Mocha([ˈmoʊkə] 摩卡)是一个单元测试框架/库,它可以用来写测试用例
  3. Sinon(西农)是一个 spy / stub / mock 库,用以辅助测试(使用后才能理解)

步骤

1. 安装各种工具:

npm i -D karma karma-chrome-launcher karma-mocha karma-sinon-chai mocha sinon sinon-chai karma-chai karma-chai-spies

2. 创建 karma 配置

在项目根目录下创建karma.conf.js

 // 新建 karma.conf.js,内容如下
 module.exports = function (config) {
     config.set({

         // base path that will be used to resolve all patterns (eg. files, exclude)
         basePath: '',

        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['mocha', 'sinon-chai'],
        client: {
            chai: {
                includeStack: true
            }
        },


        // list of files / patterns to load in the browser
        files: [
            'dist/**/*.test.js',
            'dist/**/*.test.css'
        ],


        // list of files / patterns to exclude
        exclude: [],


        // preprocess matching files before serving them to the browser
        // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors: {},


        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['progress'],


        // web server port
        port: 9876,


        // enable / disable colors in the output (reporters and logs)
        colors: true,


        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,


        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: true,


        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['ChromeHeadless'],


        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: false,

        // Concurrency level
        // how many browser should be started simultaneous
        concurrency: Infinity
    })
}

3. 将测试用例搬到test/button.test.js 文件

// 创建 test/button.test.js 文件
 const expect = chai.expect;
 import Vue from 'vue'
 import Button from '../src/button'

 Vue.config.productionTip = false
 Vue.config.devtools = false

 describe('Button', () => {
     it('存在.', () => {
         expect(Button).to.be.ok
     })
     it('可以设置icon.', () => {
         const Constructor = Vue.extend(Button)
         const vm = new Constructor({
         propsData: {
             icon: 'setting'
         }
         }).$mount()
         const useElement = vm.$el.querySelector('use')
         expect(useElement.getAttribute('xlink:href')).to.equal('#i-settings')
         vm.$destroy()
     })
     it('可以设置loading.', () => {
         const Constructor = Vue.extend(Button)
         const vm = new Constructor({
         propsData: {
             icon: 'setting',
             loading: true
         }
         }).$mount()
         const useElements = vm.$el.querySelectorAll('use')
         expect(useElements.length).to.equal(1)
         expect(useElements[0].getAttribute('xlink:href')).to.equal('#i-loading')
         vm.$destroy()
     })
     it('icon 默认的 order 是 1', () => {
         const div = document.createElement('div')
         document.body.appendChild(div)
         const Constructor = Vue.extend(Button)
         const vm = new Constructor({
         propsData: {
             icon: 'setting',
         }
         }).$mount(div)
         const icon = vm.$el.querySelector('svg')
         expect(getComputedStyle(icon).order).to.eq('1')
         vm.$el.remove()
         vm.$destroy()
     })
     it('设置 iconPosition 可以改变 order', () => {
         const div = document.createElement('div')
         document.body.appendChild(div)
         const Constructor = Vue.extend(Button)
         const vm = new Constructor({
         propsData: {
             icon: 'setting',
             iconPosition: 'right'
         }
         }).$mount(div)
         const icon = vm.$el.querySelector('svg')
         expect(getComputedStyle(icon).order).to.eq('2')
         vm.$el.remove()
         vm.$destroy()
     })
     it('点击 button 触发 click 事件', () => {
         const Constructor = Vue.extend(Button)
         const vm = new Constructor({
         propsData: {
             icon: 'setting',
         }
         }).$mount()

         const callback = sinon.fake();
         vm.$on('click', callback)
         vm.$el.click()
         expect(callback).to.have.been.called

     })
 })

4. 创建测试脚本

在 package.json 里面找到 scripts 并改写 scripts

"scripts": {
  "dev-test": "parcel watch test/* --no-cache && karma start",
  "test": "parcel build test/* --no-cache --no-minify && karma start --single-run"
},

这里被卡了很久,着实被恶心到了

windows中的script中的多个脚本使用“&&” 连接,但是只能执行前面一句

尝试了使用个各种方法后:

偶然的一次,删除node_modules

使用yarn istall

再运行npm run test就可以了,我也不知道发生了什么,就是很离谱

5. 运行测试脚本

  1. 要么使用 npm run test 一次性运行

框架搭建&持续集成(二)

这样我们就实现了只要敲一行代码,就能进行自动化测试

上图显示6个测试用例已经跑通了

当我们运行npm run test这句话的时候:

  • 先帮我们打包test/button.test.js中的测试用例,到dist/目录下,生成打包后的浏览器能识别的js文件和css文件

  • 帮我们打开一个chrome浏览器

  • 输入网址

  • 运行测试用例,即打包后的文件

  • 关闭浏览器

处理一下报错,报错是因为在button组件中使用了g-icon组件,因此我们需要注册这个组件

框架搭建&持续集成(二)

一种是全局注册

import Icon from './icon.vue'
Vue.component('g-icon',Icon)

另外一种方法是使用局部组件

import vue from 'vue'
import Icon from './icon.vue'
export default {
    components:{
      'g-icon':Icon
    }
    ...
}

如果运行npm run test报错找不到vue,那么就要使用

rm -rf .cache dist,删除掉这2个目录,重新打包,因为每次打包完都会有“残渣”

整理一下思路

  • 运行npm run test后会运行package.json中的script脚本
  • parcle build test/* --no-cache --no-minify的意思是让parcle打包test目录下的所有文件,不要缓存,不要压缩
  • 接着karma start --single-run就启动karma只运行一次
  • karma如何运行,就要在karma.conf.jskarma的配置文件中进行描述
  • 其中
files: [
    'dist/**/*.test.js',
    'dist/**/*.test.css'
],

就是要告诉karma,我们的测试用例在哪里,其中dist/**表示加载dist目录下的所有子文件(如dist/a/b/c/d/test.js),如果只用一个星dist/*就表示,只加载dist目录下的一级文件。如果不加test.css那么运行测试用例时,如果测试用例中用到了样式,而又没有加载默认的css就会报错

也就是说parcel打包的时候会将css和js分开打包

browsers: ['ChromeHeadless'],

这个就是告诉karma要打开哪个浏览器

ChromeHeadless 无头浏览器的意思就是没有界面的浏览器,因为我们做测试的时候只要看浏览器中的log信息就可以了,因此不需要界面

=============================分割=============================

备注:

  • 如果没有安装parcel但是想要使用parcl单独打包文件,可以使用npx parcel build test/* --no-cache --no-minify
  • 为什么要打包?因为test/button.test.js测试文件中,使用import格式引入了Vue、Button等模块,这句语法浏览器是不认识的,打包会把浏览器不认识的语法变成浏览器能认识的语法,比如拷贝vue的源代码,把vue做成变量暴露出来

打包前的js文件只有81行代码

框架搭建&持续集成(二)

但是打包后的js文件就变成了2万多行了

框架搭建&持续集成(二)

其实打包后的js文件,大部分都是引入的vue的源代码及引入的其他文件

二、使用Mocha& Chai做单元测试

之前的测试用例

看下之前是如何做测试的

我们使用的chai中的断言expect,使用“{}”来做作用域隔离,结合spies来mock一个假的函数,来做单元测试的

单元测试中最重要的两件事就是作用域隔离和断言


import chai from 'chai'
import spies from 'chai-spies'

chai.use(spies)
// 单元测试icon
{
    const Constructor = Vue.extend(Button);
    const vm = new Constructor({
        propsData: {
            icon: 'setting'
        }
    });
    // mount到内存中
    vm.$mount();
    let useElement = vm.$el.querySelector('use');
    let href = useElement.getAttribute('xlink:href');
    expect(href).to.eq('#i-setting');
    vm.$el.remove();
    vm.$destroy();
}

// 单元测试loading
{
    const Constructor = Vue.extend(Button);
    const button = new Constructor({
        propsData: {
            icon: 'setting',
            loading: true
        }
    });
    // mount到内存中
    button.$mount();
    let useElement = button.$el.querySelector('use');
    let href = useElement.getAttribute('xlink:href');
    expect(href).to.eq('#i-loading');
    button.$el.remove();
    button.$destroy();
}

// 单元测试svg的样式order
{
    const div = document.createElement('div');
    document.body.appendChild(div);
    const Constructor = Vue.extend(Button);
    const vm = new Constructor({
        propsData: {
            icon: 'setting'
        }
    });
    // mount到内存中
    vm.$mount(div);
    let svg = vm.$el.querySelector('svg');
    let order = window.getComputedStyle(svg).order;
    expect(order).to.eq('1');
    vm.$el.remove();
    vm.$destroy();
}

// 单元测试iconPosition
{
    const div = document.createElement('div');
    document.body.appendChild(div);
    const Constructor = Vue.extend(Button);
    const vm = new Constructor({
        propsData: {
            icon: 'setting',
            iconPosition: 'right'
        }
    });
    // mount到内存中
    vm.$mount(div);
    let svg = vm.$el.querySelector('svg');
    let order = window.getComputedStyle(svg).order;
    expect(order).to.eq('2');
    vm.$el.remove();
    vm.$destroy();
}

// 单元测试 监听button组件的click事件
{
    const Constructor = Vue.extend(Button);
    const vm = new Constructor({
        propsData: {
            icon: 'setting',
            iconPosition: 'right'
        }
    });
    vm.$mount();
    let spy = chai.spy(function (){})
    vm.$on('click', spy);
    let button = vm.$el;
    button.click();
    expect(spy).to.have.been.called()
}

改用用mocha和chai 做测试

再来看下现在的是如何做测试的

karma是负责打开浏览器

使用karma后,mochasino-chai 会自动引入,因为这2个函数是挂window上的全局函数,所以不用手动的去引

有了mocha,就可以用describe ... it...

sino-chai 就是同时引入 sinochai,sino就是用来做fake函数。chai是用来实现expect

sino-chai提供了calledwithAPI,sino-chaisinochai拉到一起合作

框架搭建&持续集成(二)

我们看到的命令行中的字都是reporters来做的

框架搭建&持续集成(二)

框架搭建&持续集成(二)


import sinon from 'sinon';

const expect = chai.expect;
import Vue from 'vue';
import Button from '../src/button';

Vue.config.productionTip = false;
Vue.config.devtools = false;

describe('Button', () => {
    it('存在.', () => {
        expect(Button).to.be.ok;
    });
    it('可以设置icon.', () => {
        const Constructor = Vue.extend(Button);
        const vm = new Constructor({
            propsData: {
                icon: 'setting'
            }
        }).$mount();
        const useElement = vm.$el.querySelector('use');
        expect(useElement.getAttribute('xlink:href')).to.equal('#i-setting');
        vm.$destroy();
    });
    it('可以设置loading.', () => {
        const Constructor = Vue.extend(Button);
        const vm = new Constructor({
            propsData: {
                icon: 'setting',
                loading: true
            }
        }).$mount();
        const useElements = vm.$el.querySelectorAll('use');
        expect(useElements.length).to.equal(1);
        expect(useElements[0].getAttribute('xlink:href')).to.equal('#i-loading');
        vm.$destroy();
    });
    it('icon 默认的 order 是 1', () => {
        const div = document.createElement('div');
        document.body.appendChild(div);
        const Constructor = Vue.extend(Button);
        const vm = new Constructor({
            propsData: {
                icon: 'setting',
            }
        }).$mount(div);
        const icon = vm.$el.querySelector('svg');
        expect(getComputedStyle(icon).order).to.eq('1');
        vm.$el.remove();
        vm.$destroy();
    });
    it('设置 iconPosition 可以改变 order', () => {
        const div = document.createElement('div');
        document.body.appendChild(div);
        const Constructor = Vue.extend(Button);
        const vm = new Constructor({
            propsData: {
                icon: 'setting',
                iconPosition: 'right'
            }
        }).$mount(div);
        const icon = vm.$el.querySelector('svg');
        expect(getComputedStyle(icon).order).to.eq('2');
        vm.$el.remove();
        vm.$destroy();
    });
    it('点击 button 触发 click 事件', () => {
        const Constructor = Vue.extend(Button);
        const vm = new Constructor({
            propsData: {
                icon: 'setting',
            }
        }).$mount();

        const callback = sinon.fake();
        vm.$on('click', callback);
        vm.$el.click();
        expect(callback).to.have.been.called;

    });
});

每个it的作用就是将不同的测试用例分开(使用it中的函数进行分隔),并给每个测试用例起名字,函数中代码是测试用例的代码,这里面的代码和之前测试的代码基本使一样.只不过是将之前的两个“{}”,换成了it

为什么用describeit呢?

这种测试方法叫BDD,行为驱动测试

看下伪代码

框架搭建&持续集成(二)

我们的测试用例,就是表述了button组件的一系列行为,它存在、它可以设置icon、它可以设置loading,同描述人类一样,他有一个头、他有2个眼、他可以跑... ...

解释一下下面这个测试用例

it('点击 button 触发 click 事件', () => {
    const Constructor = Vue.extend(Button);
    const vm = new Constructor({
        propsData: {
            icon: 'setting',
        }
    }).$mount();

    const callback = sinon.fake();
    vm.$on('click', callback);
    vm.$el.click();
    expect(callback).to.have.been.called;

});

下面的测试用例,就是测试g-button 组件中的butto按钮有click点击事件。

做测试的时候,我们就要主动触发click点击事件,看下点击事件的函数有没有执行

如果我们用普通的匿名函数作为callbak可以吗?

it('点击 button 触发 click 事件', () => {
    const Constructor = Vue.extend(Button);
    const vm = new Constructor({
        propsData: {
            icon: 'setting',
        }
    }).$mount();

    const callback = function(){};
    vm.$on('click', callback);
    vm.$el.click();
    expect(callback).to.have.been.called;

});

是不可以的,从技术方面来说,我们是没法知道function(){}被调用了

将好比,只给我们一个变量函数f1,我们有什么方法能知道f1什么时候被调用了吗?

怎么办呢?

我们需要借助别人写好的库叫sinon(相当于之前用的spies"间谍"),sinon.fake就是sinon提供的假的函数,这个函数有个特点,就是它知道自己有没有被调用过,也知道自己被调用的时候传了什么参数

所以才能有后面的断言 expect(callback).to.have.been.called; --> 这个假的函数被调用了

目前为止三个文件的功能我们已经搞清楚了,这三个文件分别对应package.json(主要是配置脚本)、button.test.js(测试用例)和karma.conf.js(karma自动测试的配置文件)

具体测试用例的语法怎么写?

记住最常用的语法

expect(xxx).to.equal(yyy)意思是期待xxx = yyy,其中equal可以简写为eq

eg:期待某个变量是数组

expect(xxx instancof Array).to.eq(true)

前面放期待的东西,后面放true,就可以做很多测试

测试用例的很多语法都是chai.js 提供的

框架搭建&持续集成(二)

图中蓝色部分的语法,是我们在写测试用例可能要用到的语法

橙色部分的相当于语气词,没有实际的意义,可以省略,不会影响测试语法的准确性,只是加上读取来更加顺口

重点说一下deep的用法

expect([1,2]).to.eq([1,2])   // false, 这里对象的比较,比较的是对象的地址,2个不同的对象地址不同

expect([1,2]).to.deep.eq([1,2]) // true,这里比较的是对象的内容

类似于深拷贝和浅拷贝

备注

  • itdescribe来源于mocha库,也就是说行为驱动测试BDD是mocha引入的
  • expect是从来源于chai库,也就说具体的断言是由chai.js引入的

自动测试

改用watch而不是parcel

目前做到的效果是,每次修改代码,还要运行npm run test重新打包和测试

能不能做到,每次改代码不要重新运行npm run test

// package.json
"scripts": {
  "dev-test": "start parcel watch test/* --no-cache && karma start",
  "test": "parcel build test/* --no-cache --no-minify && karma start --single-run"
},

我们改用dev-test来跑代码

dev-test和test区别:

  1. 将build改为parcel
  2. 之前karma只运行一次 --single-run,现在是不中断运行

这样只要改了代码,parcle就会重新打包代码,karma重新测试

Windows 用户运行 npm run dev-test 时会出现 BUG,解决办法是:

将 dev-test 对应的命令 parcel watch test/* --no-cache & karma start 分别运行,运行方式如下

  1. 新开一个 Git Bash 窗口运行 npx parcel watch test/* --no-cache
  2. 再开一个 Git Bash 窗口运行 npx karma start

或者尝试在第一条脚本语句前加一个start

windows中不支持多条脚本语句,最好还是npm run test

到这里,我们只需要专注于写代码,其他的交给parcel自动打包 + karma 自动测试

还有没有优化的余地呢?

能不能做到,不运行npm run dev-test 也能自动的完成测试呢?

也就是说能不能什么都不运行,就能帮我们完成测试呢?

三、使用CircleCI做持续集成

CircleCI

circle官网关于测试的文档

我们是不是可以尝试雇一台机器帮我们运行npm run dev-test这一行代码?

这台机器每天要做的事情就是,帮我们把要测试的代码copy过去,然后运行测试用例

这台机器叫CircleCI:持续集成服务(TravisCI已经不免费使用了)

框架搭建&持续集成(二)

框架搭建&持续集成(二)

这样就表示测试通过了!

这里埋一个坑

我们需要在.circleci/config.yml中自定义自己的持续测试配置文件,这里暂时还不知道怎么写这个配置文件

我们后续只要往github中项目push代码就可以了,测试交给CircleCI,它会接管这个项目,持续的自动的测试我们的代码

这就是持续集成中的一部分-- 持续测试

持续集成包括持续测试、持续交付、持续部署等

持续集成的重点在“持续”

为什么要持续呢?

拿持续测试举例子,持续的意思就是每天要做的事,持续的好处就是尽早发现bug,防止在有bug的代码上继续开发,导致bug积累bug,最终无法找到解决bug的办法

这样,每天写完代码就push一次,做一次持续测试,如果有问题,当天就修改完。这样在每一天早上,开发新代码的时候,代码都是正确的、没有bug的

同样的如果是多人合作的项目,项目组中的每个成员都单独的push,单独的做持续测试,这样持续的往项目中集成东西,这样就会让项目运行稳定,而不会出现一合并全是bug

或者使用github中的GitHub Actions和gitlab做持续集成

四、使用npm发布自己的包

发布包

如何让项目能被全世界的程序员使用?我们需要将项目发布到npm

1. 确保你的代码测试通过了

npm run test 全部是绿色才行,如果有问题请不要发布你的代码

2. 上传代码到npmjs.org

  • 更新 package.json

    • 在 package.json 里将版本号改为 0.0.1,等我们把项目全部做完了才将版本号改为 1.0.0
    • 创建 index.js,在 index.js 将你想要导出的内容告诉npm,导出想要导出的全部组件,index.js就是作为发布到npm中项目的入口文件
import Button from './src/button.vue'  
import GButtonGroup from './src/g-button-group.vue';  
import Icon from './src/icon.vue'  
  
export {Button,GButtonGroup,Icon}
  • package.json中的main指定为index.js作为入口文件

  • 去 www.npmjs.com/ 注册一个账户,username才是你的登录名

  • 确认一下邮箱(必须)

  • 在你的项目根目录运行 npm adduser

    • 如果错误提示里面含有 registry.npm.taobao.org 则说明你的 npm 源目前为淘宝源,需要更换为 npm 官方源
    • nrm use npm
  • 运行 npm publish(是从本地发布)

框架搭建&持续集成(二)

看到这样就表示发布到npm成功了

我们尝试下载上传到npm中代码npm i g-design-of-vue

我们的代码放在/node_modules/g-design-of-vue中

框架搭建&持续集成(二)

那我们怎么知道我们的代码别人是不是可以使用呢?

因此我们需要自己用一下自己的包,来确保别人也可以使用

 使用自己的包

因此,我们得猜比人如何使用我们的包?

我们的包是vue的UI组件,因此使用我们组件的人就是vue的用户,那么vue的用户会有三种方法来使用我们的包

0.预测其他使用你的包的人会怎么使用

  • 使用 vue-cli
  • 使用 webpack
  • 使用 parcel

1.分别使用这些方式来使用自己的包(我们只以 vue-cli 为例)

  • vue的使用者会在空目录中运行npm install -g @vue/cli@4.0.0(本项目适用于vue2,vue/cli在4.5.0版本以下都是vue2.0),安装vue
  • vue create hello-world 创建一个hello world项目
  • cd hello-world
  • npm run serve --no-cache
  • 访问http://localhost:8080/

框架搭建&持续集成(二)

  • 安装我们的项目npm i g-design-of-vue,我们的项目会安装到用户的node_modules/d-design-of-vue目录下

框架搭建&持续集成(二)

  • 用户就到他自己项目中的main.js中引入我们的UI组件库,并使用我们的组件
import {Button,GButtonGroup,Icon} from 'g-design-of-vue'

 <g-button>UI组件库</g-button>

使用过程中我们发现报错说 import 语法有问题,那是因为 node 目前确实不支持 import,我们需要用 babel 转译 import

  • 你可以要求使用者自己用 babel 来转译

  • 你也可以转义好了再给他用

    • 回到我们的项目目录下运行npx parcel build index.js --no-minify --no-cache 将index.js变成不含import的index.js(本来不应该加 --no-minify 的,奈何不加会有 bug,HTML 压缩把 slot 标签全删了)

    • 修改 package.json 的 main 由index.js改为打包编译后的浏览器能认识的语法的dist/index.js

    • 即使我们项目的.gitignore中不提交dist目录,但是不影响发布到npm,npm能看到dist目录的文件

框架搭建&持续集成(二) 每次重新发布到npm前,一定要修改package.json中的版本号 发布包到npm之前记得将npm的源切换到npm而不是使用taonbao源

  • 用户回到他的项目中重新安装我们的包npm i g-design-of-vue@latest

框架搭建&持续集成(二)

用户成功使用了我们的组件

但是当前的组件没有样式,为什么没有样式呢?

因为我们的项目在打包的时候,将index打包成了2个文件,一个是index.js,另外一个是index.css(导出的组件的样式)

因此我们需要手动的引入css

能不能自动引入?最好不要,因为如果css放到js中,js会变得很大,分开更容易缓存

  • 用户引入css文件import 'g-design-of-vue/dist/index.css'

框架搭建&持续集成(二)

原因是css样式中用到都是变量都是自定义的

框架搭建&持续集成(二)

因此我们要在文档中告知用户,要复制这些样式

站在使用者的角度,目前的组件库还是有很多问题的

  • 用户在style标签中粘贴这些样式后,组件也有样式了

框架搭建&持续集成(二)

// 用户使用组件
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <g-button>UI组件库</g-button>
  </div>
</template>

<script>
import { GButton, GButtonGroup, GIcon } from 'g-design-of-vue'
import 'g-design-of-vue/dist/index.css'
export default {
  name: 'App',
  components: {
    'g-button': GButton
  }
}
</script>

<style>
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  --button-height: 32px;
  --font-size: 14px;
  --button-bg: white;
  --button-active-bg: #eee;
  --border-radius: 4px;
  --color: #333;
  --border-color: #999;
  --border-color-hover: #666;
  --border-active-bg: #d3d2d2;
}

#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}</style>

至此,别人就可以使用我们的组件了

用户要使用我们的组件只需要做三件事

  1. 引入想要使用的组件
  2. 引入g-design-of-vue/dist/css
  3. 引入样式变量

后面会将样式变量改为scss

目前,每改一行代码,都要上传到npm,太麻烦了

如何不上传到npm,就能测试出代码在被人使用的时候会不会出bug??

五、npm link 的使用

我们的轮子并不知道怎么才是最好的,但是如果我们能加快造轮子的效率,就可以让我们的轮子达到更好的状态

当前的效率瓶颈是,每次修改完代码都得npm publish,用户都得npm install

我们能不能先自己调好了再给用户?

我们不用升级package.json中的版本,就可以自己测自己

如果,我们修改了项目的代码,如在g-icon组件中加了一个reagen样式,本机的用户如何得到最新的代码呢?

  • 我们要在自己的项目中运行npm link
  • 用户(本机模仿自己是用户)在自己的目录中 npm link g-design-of-vue

框架搭建&持续集成(二)

框架搭建&持续集成(二)

框架搭建&持续集成(二)

看来是可以了

下次每次我们的项目改完代码就不用再npm link和 用户的项目也不用 npm link g-design-of-vue

改完代码,我们只需要使用parcel重新打包编译我们项目中的文件即可,用户那边会自动更新(如果每次改完代码不打包编译,用户是拿不到可以运行的版本)

npx parcel build index.js --no-cache --no-minify

这样我们在写完代码后,就不需要找一个人去install我们的项目,再去测试了。我们自己就当做用户

可以实时的检查自己的代码是否在用户那可用了,就能够尽早的发现问题,解决问题,提高效率和用户体验

知识点总结

1. 单文件组件(vue)

2. Parcel(打包)

3. 单元测试({...}{...})

4. 自动测试

  • karma 测试运行器
  • Mocha(BDD风格,describe...it) 测试框架
  • chai,断言库,expect(xxx).to.equal(yyy)

5. 持续集成(Travis CI / Circle CI)

6. 发布到npm

配置package.json 发布(dist/index.js dist/index.css)

7. npm link / yarn link

加快造轮子过程

转载自:https://juejin.cn/post/7254549436626550842
评论
请登录