blog

在知乎上看到 赵雨森同学 提到前端工程化有四个方面,模块化、组件化、规范化、自动化,本人十分赞同,我在工作中也慢慢这几个方向作出了总结

模块化

模块化只是在语言层面上,对代码的拆分;而组件化是基于模块化,在设计层面上,对UI(用户界面)的拆分

js 的模块化

现在ES6已经在语言层面上规定了模块系统,完全可以取代现有的CommonJS和AMD规范,而且使用起来相当简洁

css 的模块化

目前使用了这三方式处理:

组件化

组件化是基于模块化的,因为组件的单位可以有模板,样式加逻辑。

另,将你所能看见到的视图(UI)进行合理拆分得到的单元,并能让它达到可复用程度,可称之为组件。组件的方案采用 vuejs 的单文件组件

规范化

为了更好的落实开发,可以制定一些规范

编码规范

  1. js使用eslint,目前采用 google 的 javascript style guide
  2. css使用相应的stylelint
  3. 使用editorconfig,统一编辑器或ide的一些设定,如js缩进为2空格

前后端接口规范

采用 restful 风格,接口描述使用swagger

对于某些接口返回状态码还是中文结果,前端应尽量不让去判断状态,只作显示

版本控制

node module 遵循unix的思想–do one thing and do it well,也因此单个上层的模块会依赖很多下层的模块,这可能会导致其中一个下层的模块改变,导致整个上层模块崩溃。

package.json 里的包版本号应写死,除非因某个包有了新需求特性,再去更新

目录结构

编码规范

长命名使用驼峰式。类使用 ClassName,而方法名或属性使用 classProperty

协作工具

这里指的是协作工具的采用

其它规范

自动化

环境控制

使用docker自动化部署,集群使用 kubernetes(k8s)

构建工具

目前使用webpack/rollup

持续化集成

项目徽章

无论是开源项目还是私有项目都可以使用徽章查看状态

前端技术选型

基于以上工程化流程,技术选型如下:

前端项目配置

css

reset

css reset 采用 normalize.css

布局

不考虑兼容的情况下,一维用 flexbox,二维用 css grid,单位 rem/vm vw,更改盒模型为 box-sizing减少padding和border的计算;考虑兼容性则使用 bootstrap3 提供的grid布局方案

动画库

hover,animate.css,velocity

sass

sass 存在 Duplicate import problem

暂时没去解决,现有以下可以解决办法

结论是尽量不要使用引用, variable或者function之类的可以使用

参考地址 http://ryerh.com/sass/2016/03/15/vue-webpack-duplicate-sass-import.html

webpack

noParse

webpack会花很多的时间查找一个库的依赖,使用该参数可以在webpack 中忽略对已知文件的解析

例如,这里我们可以确定 vue 是没有依赖项的,配置如下

// 支持正则匹配文件名
 module :{
   noParse: {
     'vue': './node_modules/vue/vue.min.js'
   }
 }

这样我们在项目中可以使用

import vue from 'vue'

alias

为引入模块提供别名,这个可以减少webpack去查找引入模块位置的时间,同时也为我们开发中引入公用模块提供方便

resolve: {
    alias: {
        'ui': path.resolve(__dirname, 'app/compontens/ui'),
        'fonts': path.resolve(__dirname, 'app/assets/fonts')
    }
}

以上配置可以让我们在需要引用公用组件时不必考虑目录层级的问题

import modal from 'ui/modal.vue'

css如果要使用webpack中的alias,需要在alias名前加上 ~

@font-face {
    url( "~fonts/iconfont.woff") format('woff')
}

uglifyJs

// 去除console
new webpack.optimize.UglifyJsPlugin({
  compress: {
    warnings: false,
    pure_funcs: [ 'console.log', 'console.info' ]
  },
}),

tree shaking

让webpack理解es6 的导入机制,例如现在有两个文件

// utils.js
export function foo() {
    return 'foo';
}
export function bar() {
    return 'bar';
}
// app.js
import { foo } from './utils'

如果不使用 tree-shaking,app.js编译输出为

/***/ function(module, exports) {

  'use strict';

  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.foo = foo;
  exports.bar = bar;
  // utils.js
  function foo() {
    return 'foo';
  }
  function bar() {
    return 'bar';
  }

/***/ }

可以看到上面包含了 foo 和 bar 两个函数,把utils里的内容全部打包进去了,如果使用tree-shaking,输出结果是这样的

/***/ (function(module, __webpack_exports__, __webpack_require__) {

"use strict";
/* harmony export (immutable) */ __webpack_exports__["a"] = foo;
/* unused harmony export bar */
// utils.js
function foo() {
  return 'foo';
}
function bar() {
  return 'bar';
}
/***/ }),

我们可以看到哪些方法是没有被使用的,你可以通过 --optimize-minimize 参数压缩代码剔除未被使用的函数

// 脚本
  "scripts": {
    "build": "webpack --optimize-minimize",
    "seebuild": "webpack"
  }

// 通过格式工具查看到的结果
function(t, e, n) {
  "use strict";
  function r() {
    return "foo"
  }
  e.a = r
}

已经没有bar了

babel

在项目下创建一个 .babelrc 的配置文件。目前通过插件babel主要提供了以下几个功能

  1. 在vue中异步加载可将 system.import 转为 import()
  2. 使用 tree shaking
  3. 使用 es6/7 语法及特性

性能

图片

前端常用库

待补充

最后

附上一个后台项目 demo