前端架构之路(6) - 组件化

组件化

1. 什么是 “组件化”

组件化就是将项目中能够共用的代码提取出来,单独成一个组件,以便在多个地方调用此组件,这样即可以作到只维护一份代码,而不须要每次更新都要改多个地方,并且还不能保证都同样。css

组件化通常分为项目内的组件化和项目外的组件化。html

2. 项目内组件化

项目内的组件化,就是一个项目中能够共用的代码提取出来,独立成组件,供项目其余地方调用。好比像上一节推荐使用的目录结构中的 component 目录:jquery

|-- project/ 工程目录
    |-- src/ 源代码目录
        |-- component/ 全局组件目录
        |-- util/ 全局工具函数目录
        |-- ...

项目内的组件化对于单个项目是很适用,但当组件须要被跨项目使用(多个项目同时使用)时,便有些棘手了。webpack

3. 完全组件化

完全组件化就是将组件独立成一个项目,若是须要在其余项目使用这个组件,就须要依赖这个项目。这个时候,组件化通常都是搭配版本管理工具和版本管理系统一块儿使用。git

比较经常使用的版本管理工具备 gitsvnes6

版本管理系统以 gitlab 为例进行说明。github

3.1 目录结构示例

|-- project1/ 项目1
    |-- package.json
    |-- .gitignore
    |-- README.md
    |-- lila.config.js
    |-- ...
    |-- project/ 工程目录
        |-- src/ 源代码目录
            |-- component/ 项目内组件目录
            |-- util/ 全局工具函数目录
            |-- ...

|-- component1/ 组件1
    |-- package.json
    |-- .gitignore
    |-- README.md
    |-- webpack.config.js
    |-- src/ 源代码目录
    |-- ...

|-- component2/ 组件2
    |-- package.json
    |-- .gitignore
    |-- README.md
    |-- webpack.config.js
    |-- src/ 源代码目录
    |-- ...

3.2 使用组件

project1 中安装 component1, component2 依赖。web

# package.json
{
    "dependencies": {
        "component1": "git+http://yourGit.com/yourName/component1.git#0.0.1",
        "component2": "git+http://yourGit.com/yourName/component2.git#0.0.1"
    }
}

# code
// commonjs
const component1 = require('component1');
// es6
import component1 from 'component1';

通常来讲,独立化组件要有 私有包命名前缀apache

# package.json
{
    "dependencies": {
        "@yourCompany/component1": "git+http://yourGit.com/yourName/component1.git#0.0.1",
        "@yourCompany/component2": "git+http://yourGit.com/yourName/component2.git#0.0.1"
    }
}

# code
// commonjs
const component1 = require('@yourCompany/component1');
// es6
import component1 from '@yourCompany/component1';

独立化组件与私有 npm 仓库配合使用是最完美的,下一节 私有 npm 仓库 将会讲到。npm

# npm
$ npm config set registry http://your.company.npm.registry.com

# package.json
{
    "dependencies": {
        "@yourCompany/component1": "^0.0.1",
        "@yourCompany/component2": "^0.0.1"
    }
}

# code
// commonjs
const component1 = require('@yourCompany/component1');
// es6
import component1 from '@yourCompany/component1';

4. 使用构建工具

团队开发组件化以后,就会有大量的组件产生。与诸多项目同样,如何既能快速开发,又有规范可循,维护成本最小化,固然仍是得用构建工具呀。

yume 构建工具为例进行说明。

4.1 安装工具

npm install yume -g

4.2 新建项目

yume new yume-demo && cd yume-demo && npm install yume --save-dev

4.3 根据须要更新配置文件

配置文件在项目根目录下 yume.config.js 中。

module.exports = {
    // 模块定义
    modules: {
        index: {
            js: 'src/index.js',
            filename: 'demo',
            library: 'Demo',
            libraryTarget: "umd"
        },
        ui: {
            html: 'ui/index.html',
            js: 'ui/index.js'
        },
        demo: {
            html: 'demo/index.html',
            js: 'demo/index.js'
        },
        example: {
            html: 'example/index.html',
            js: 'example/index.js'
        }
    },
    // 外部依赖包(不须要被打包进 dist 文件中)
    externals: {
        jquery: {
            commonjs: 'jquery',
            amd: 'jquery',
            commonjs2: 'jquery',
            root: 'jQuery'
        },
        ...
    },
    // 单独打包 css
    packCssSeparately: true,
    ...
};

4.4 开发项目

yume dev moduleName

4.5 打包项目

yume dist moduleName

这个时候,会在 dist 目录中生成相应的包文件,而后运行 npm publish 就能够发布到远程仓库中了。

5. 动态开发组件

组件开发中有一个比较突出的问题,就是不少组件每每是与实际项目有强依赖性,须要与实际项目进行实时调试,而实际项目又是以版本化在管理组件,不能作到实时更新组件代码,组件必须发布一个版本,实际项目才能更新,这极大的下降了开发效率和便利性。

解决这个问题固然仍是须要构建工具的支持。以 lilayume 为例进行说明:

目录结构是这样的

|-- projects/
    |-- project1/ 项目1
    |-- project2/ 项目2
    |-- component1/ 组件1
    |-- component2/ 组件2

project1 中代码是这样的

# package.json
{
    "dependencies": {
        "@yourCompany/component1": "^0.0.1"
    }
}

# code
require('@yourCompany/component1/dist/component1.css'); // css 文件
const component1 = require('@yourCompany/component1'); // 主文件

配置 lila.config.js,让项目支持动态加载 @yourCompany/component1 的开发代码

module.exports = {
    ...,
    // 添加一个 `resolve.modules`(添加一个 webpack 加载包基地址)
    resolveModules: [
        '../'
    ],
    // 别名配置(只有当命令行中有 `-o|out` 参数时才生效)
    outResolveAlias: {
        '@yourCompany/component1/dist/component1.css': 'component1/dist/component1.css',
        '@yourCompany/component1': 'component1/dist/component1.js'
    }
}

dev, dist @yourCompany/component1 组件的本地开发代码

运行 dev, dist, sync 命令时加上 -o, --out 参数,就能够加载 @yourCompany/component1 组件的本地开发代码

# dev
$ lila dev moduleName -o

# 正常运行,加载 0.0.1 版本中的代码
$ lila dev moduleName

# dist
$ lila dist moduleName -e 1 -out

# sync
$ lila sync moduleName -e 2 --out

6. 后续

上一篇:构建工具 for teamwork

下一篇:私有 npm 仓库

更多博客,查看 https://github.com/senntyou/blogs

做者:深予之 (@senntyou)

版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证