用gulp替代fekit构建前端项目

https://segmentfault.com/a/1190000003060016

离开qunar有一个多月了,在离开的时候就决定不再用fekit。做出这个决定并不是因为fekit不好,恰恰相反,fekit帮我们做了很多事情,还屏蔽了许多细节,让开发人员能够专注于开发过程。不过随着fekit的升级,也出现了一些问题,同时fekit和公司业务及发布流程有一定耦合,所以觉得采用开源的构建方案。

在使用gulp的过程中,基本也是依据使用fekit的思路来逐步完善构建过程的,所以还是要感谢fekit。现在进入正题,
看看利用gulp如何实现本地服务、mock数据、css预处理、js模块化、打包压缩、版本号替换等功能的。

1. 本地服务

依赖模块:gulp-webserver

使用:

gulp.task(‘webserver‘, function() {
    gulp.src(‘./app‘)
        .pipe(webserver({
            livereload: true,
            directoryListing: {
                enable:true,
                path: ‘app‘
            },
            host: ‘172.16.100.27‘,
            port: 8000
        }));
});

注意:

  1. app是你的项目目录,比如我的目录结果如下

    -app
        |--- src
        |--- images
        |--- mock
        |--- prd
        |--- index.html
    
    -gulpfile.js
  2. 开启directoryListing的enbale,访问根目录(172.16.100.27:8000)时才能显示目录或文件列表。
  3. host可以是ip也可以是域名,不过在虚拟机里面调试时,用域名访问似乎有点问题,没有深究;如果要在手机上调试,同样建议用ip。

2. mock 数据

依赖模块:gulp-webserver

使用:请参考之前的博文 gulp构建之mock data(模拟数据、转发请求)

3. css 预处理编译

依赖模块:gulp-sass gulp-minify-css gulp-autoprefixer

使用:我这里使用的是sass

var sass = require(‘gulp-sass‘),
    minifyCSS = require(‘gulp-minify-css‘),
    autoprefix = require(‘gulp-autoprefixer‘);

var cssFiles = [
    ‘app/src/styles/page/index.scss‘,
    ‘app/src/styles/page/touch.scss‘
];

/* 编译压缩sass文件 */
gulp.task(‘sass‘, function() {
    gulp.src(cssFiles)
        .pipe(sass().on(‘error‘, sass.logError))
        .pipe(autoprefix())
        .pipe(minifyCSS())
        .pipe(gulp.dest(paths.build.styles));
});

注意:

  1. 使用sass模块时,要加上.on(‘error‘, sass.logError)),这样sass编译出错时会打log,而不是终止运行。
  2. autoprefix,这是一个好东西,也是我不用fekit的一个原因(它还没集成autoprefix)

4. js 模块化开发

依赖模块:gulp-webpack gulp-uglify vinyl-named imports-loader

说明:fekit采用的CommonJs的模块化方式,此外还有requireJS这种AMD的模块化方式。而webpack则是理想中的打包工具,它同时支持CommonJs和AMD,并拥有大量的加载器,包括上面说都的sass编译、前端模板编译等加载器,而且还有webpack-dev-server,已经强大到几乎不需要gulp了。我对webpack还不太熟,并且需要用到gulp的一些其他功能,所以暂时考虑把webpack作为gulp的一个模块来使用。

使用:

var named = require(‘vinyl-named‘);
var webpack = require(‘gulp-webpack‘);

var jsFiles = [
    ‘app/src/scripts/page/index.js‘,
    ‘app/src/scripts/page/touch.js‘
];

// webpack打包压缩js
gulp.task(‘packjs‘, function() {
    return gulp.src(jsFiles)
        .pipe(named())
        .pipe(webpack({
            output: {
                filename: ‘[name].js‘
            },
            module: {
                loaders: [{
                    test: /\.html$/,
                    loader: ‘mustache‘
                }, {
                    test: /\.js$/,
                    loader: "imports?define=>false"
                }]
            },
            resolve: {
                alias: {
                    jquery: ‘app/src/scripts/lib/jquery-1.11.3.min.js‘
                }
            },
            devtool: "#eval-source-map"
        }))
        .pipe(uglify().on(‘error‘, function(e) {
            console.log(‘\x07‘,e.lineNumber, e.message);
            return this.end()}
        ))
        .pipe(gulp.dest(paths.build.scripts));
});

注意:

  1. 对于有多个入口文件(entry point)的情况,需要使用vinyl-named这个模块,这样就能实现以下打包需求

    src/scripts/index.js -> prd/scripts/index.js
    src/scripts/touch.js -> prd/scripts/touch.js
    在output里面可以设置打包后的文件名,如 "[name].min.js"
    
  2. 我在项目中使用的是commonjs的模块化方式,但大多数插件(如jquery或zepto插件)都是支持两种模块化方式,并且是先判断 define 再判断 module.export,所以我们需要“屏蔽”amd的模块加载方式。
    首先安装`imports-loader`模块,然后做如下配置:
    module: {
        loaders: [{
            test: /\.js$/,
            loader: "imports?define=>false"
        }]
    }
    
    这样我们就能放心地使用各种插件了。
    
  3. 我的项目中使用了HoganJs作为前端模块,在webpack中只要找到相应的加载器就行。
    首先安装[mustache-loader](https://github.com/deepsweet/mustache-loader)模块,然后做如下配置:
    module: {
        loaders: [{
            test: /\.html$/,
            loader: ‘mustache‘
        }]
    }
    
    通过 2. 和 3. 两个例子,大家可以看出test就是要处理的文件类型,loader就是处理文件的加载器。
    
  4. 调试仍然是个比较大的问题,虽然webpack提供了各种调试模式(在devtool中配置,实现sourcemap的调试),但在实际使用时,经常会遇到跳过断点的问题,不知道是不是gulp-webserver和webpack不适配的原因。所以在实际开发中,我会先把uglify给注释掉,这样至少能在一个未混淆压缩的文件里调试。如果大家有好的方法,麻烦告知,谢谢~

5. 生成文件对应的 md5(版本号),并在 html 中引用文件时添加

依赖模块:gulp-rev gulp-rev-collector

说明:在实际生产环境中,我们页面引用的css和js文件的文件名都是带版本号的,这样方便回滚和防止缓存。通常我们使用文件的md5编码作为版本号。

使用:

var rev = require(‘gulp-rev‘),
    revCollector = require(‘gulp-rev-collector‘);

var cssDistFiles = [
    ‘app/prd/styles/index.css‘
];

var jsDistFiles = [
    ‘app/prd/scripts/index.js‘
];

// prd文件加md5后缀,并生成替换map
gulp.task(‘ver‘, function() {
    gulp.src(cssDistFiles)
        .pipe(rev())
        .pipe(gulp.dest(‘app/prd/styles‘))  // 生成 name-md5.css
        .pipe(rev.manifest())
        .pipe(gulp.dest(‘app/ver/styles‘)); // 生成 rev-manifest.json(映射)

    gulp.src(jsDistFiles)
        .pipe(rev())
        .pipe(gulp.dest(‘app/prd/scripts‘))
        .pipe(rev.manifest())
        .pipe(gulp.dest(‘app/ver/scripts‘));
});

// html文件添加md5引用
gulp.task(‘html‘, function() {
    gulp.src([‘app/ver/**/*.json‘, ‘app/*.html‘])
        .pipe(revCollector())
        .pipe(gulp.dest(‘app/‘));
});

结果如下:

index.html

<script src="prd/scripts/index.js"></script>
=>
<script src="prd/scripts/index-0884a4f91b.js"></script>

注意:

  1. 我把生产md5和替换html中的版本号拆分为了两步,之前是放在一起,结果会出现用上一次版本号替换html中文件名的问题。

6. 将外部引用的资源文件内联到 html 中

依赖模块:gulp-inline-source

说明:一些touch上的活动页,样式和脚本都不多,与其增加额外的请求数,不如把样式和脚本都以内联的方式嵌到html文件中。

使用:

gulpfile.js
// 把css、js以inline的形式插入html
gulp.task(‘inlinesource‘, function () {
    return gulp.src(‘app/index.html‘)
        .pipe(inlinesource())
        .pipe(gulp.dest(‘dist‘));
});

index.html
<link rel="stylesheet" href="../prd/styles/index.css " inline>
<script src="../prd/scripts/index.js" inline></script>

这一个月来,我用到的基本就这么多了,其实回头看看,自己东拼西凑也算是造了一个自己的构建小工具。同时,我也更深入地理解了fekit的设计思路和一些原理。

不过,类似FIS的smarty模板、fekit的velocity mock等功能,我还没发现怎么在gulp中来实现。简单的说,就是能在前端环境开发jsp、velocity或者php(我目前的需求是php),数据采用mock方式,不依赖于后端,从而把view的控制权完全拿到前端,实现前后端的分离(非ajax方式)。如果大家有任何建议,麻烦指教!



更新于08.11

7、模版层面的前后端分离

依赖模块: gulp-swig

说明:swig 是一个类django、twig模板的前端模版,说是类似,基本语法其实一样,这样前端开发用swig,后端用对应的模板引擎(比如python的django、php用twig等),这样一套模版文件在前后端都能解析,从而实现前后端分离。

由于swig和twig在一些语法上存在差异,我们需要扩展swig:

swig.setDefaults({
    cache: false,
    loader: swig.loaders.fs(path.join(appbase)),
    locals: {
        environment: "local", // 全局变量,表示本地环境,用于区分swig和twig不一样的地方
        range: function (start, end) {
            return (new Array(end-start+1)).join().split(‘,‘).map(function (n, idx) { return idx + start; });
        }
    }
});
swig.setFilter(‘length‘, function (input) {
  return input.length;
});
swig.setFilter(‘slice‘, function(input, begin, len){
    return input.slice(begin, len);
});
swig.setFilter(‘json_encode‘, function(input){
    return JSON.stringify(input);
});
swig.setFilter(‘replace‘, function(input, obj) {
    var output = input;
    for (var key in obj) {
        output = output.replace(key, obj[key]);
    }
    return output;
});

另外我在locals里面设置了environment这个字段,这样在某些地方可以通过environment判断是否是本地环境,从而解决swig和twig不兼容的问题:

{% if environment == ‘local‘ %}
    {% set tpl_path = ‘./components/ctn_publish/‘ + type + ‘/index.tpl‘ %}
{% else %}
    {% set tpl_path = ‘./components/ctn_publish/‘ ~ type ~ ‘/index.tpl‘ %}
{% endif %}
时间: 2024-10-16 18:48:39

用gulp替代fekit构建前端项目的相关文章

基于requireJS和Gulp可快速搭建前端项目的脚手架

基于requireJS和Gulp可快速搭建前端项目的脚手架. 项目地址 git clone git@github.com:perfectSymphony/Gulp-cli.git 项目目录 ├── README.md # 项目说明 |—— bin # (在gulpfile文件中使用到)解析layout中的模板html,将完整的html产出到src/html中 ├── dist # 打包生成的项目文件 |—— logs # 监听编译less文件时,打印报错信息, ├── gulpfile.js #

gulp+webpack构建前端项目

本文将介绍如何利用gulp+webpack构建一个基本的前端项目.假设你已经安装了node环境并且会使用简单的命令行 1.gulp安装 (1)全局安装 npm install gulp -g (2)查看gulp是否安装成功 gulp -v (3)进入本地目录,新建gulpfile.js 2.安装gulp-webpack插件 基于gulp的插件非常多,建议大家查看npm官网https://www.npmjs.com (1)安装 webpack的用途主要是模块化+打包.安装敲入命令 npm inst

用gulp构建你的前端项目

前言 前端技术发展日新月异,随着模块化.组件化的提出,前端变得越来越复杂,静态资源越来越多,那么对静态资源的处理,如压缩,合并,去掉调试信息.. 如果还是人工去处理,效率非常之低且还容易出错,于是自动化的处理工具也就必然出现了.就像后端我们一般用maven管理项目,那么前端gulp是个不错的选择. 什么是gulp 是一个基于 Node.js 流.Javascript语法的快速构建前端项目并减少频繁的 IO 操作的自动化工具. Gulp有什么好处 易于学习使用 通过最少的API(核心.src().

[转]gulp构建前端工程

摘要: Gulp 是一个自动化工具,前端开发者可以使用它来处理常见任务: 搭建web服务器 文件保存时自动重载浏览器 使用预处理器如Sass.LESS 优化资源,比如压缩CSS.JavaScript.压缩图片 当然Gulp能做的远不止这些.如果你够疯狂,你甚至可以使用它搭建一个静态页面生成器.Gulp真的足够强大,但你必须学会驾驭它. 这是这篇文章的主要目的.帮助你了解Gulp的基础用法,助你早日完成一统天下的大业. 在我们深入了解之前,我们先来说说为什么是Gulp. 为什么是Gulp? 类似G

vue-cli 构建vue项目

师父说,咱们还是要用vue-cli 去构建前端项目.然后我就开始了 懵逼之旅. 今天上午主要就是搞懂用webpack和vue-cli怎么搭建 运行项目 首先找到了咱们博客园 园友的博客,提供了大概五个步骤吧. 1.装node.js 装完这个就可以用npm命令去装其它东西了. 出版本号了 就代表装成功了 2.装vue-cli npm install -g vue-cli 在node的命令行界面 或者cmd的命令行 都可以输入这行命令 同理 出了版本号 就代表装成功了. 3.使用vue-cli初始化

gulp + webpack 构建多页面前端项目

修改增加了demo地址 gulp-webpack-demo 之前在使用gulp和webpack对项目进行构建的时候遇到了一些问题,最终算是搭建了一套比较完整的解决方案,接下来这篇文章以一个实际项目为例子,讲解多页面项目中如何利用gulp和webpack进行工程化构建.本文是自己的实践经验,所以有些解决方案并不是最优的,仍在探索优化中.所以有什么错误疏漏请随时指出. 使用gulp过程中的一些问题,我已经在另外一篇文章讲到了 grunt or gulp 前言 现在为什么又整了一个webpack进来呢

Gulp构建前端自动化项目

类似于Grunt,gulp是另一个同样功能很强大的前端项目自动化利器. 下面是项目的效果: 另一个页面: 要求: Node.js gulp.js bower 下载项目代码于本地, 进入该目录,执行如下命令: 1 cd my-demo2 npm install 3 bower install 安装完成之后,运行如下命令: 1 gulp 现在项目已经跑起来了,所有在src目录下的文件都会编译生成相应的文件,并存入build文件夹下,同时,src目录下的文件发生变化时,会新生成相应的文件,并且已经启动

Gulp安装及配合组件构建前端开发一体化

所有功能前提需要安装nodejs(本人安装版本v0.10.26)和ruby(本人安装版本1.9.3p484). Gulp 是一款基于任务的设计模式的自动化工具,通过插件的配合解决全套前端解决方案,如静态页面压缩.图片压缩.JS合并.SASS同步编译并压缩CSS.服务器控制客户端同步刷新. Gulp安装 全局安装Gulpjs npm install -g gulp  #全局安装 局部安装Gulpjs npm install gulp --save-dev # 局部安装 全局安装 1. 将安装包放在

Gulp构建前端自动化工作流之:常用插件介绍及使用

在对Gulp有了一个初步的了解之后,我们开始构建一个较为完整的Gulp开发环境. 本文主要分为6个段落: 1. 构建项目目录结构(Directory Structure Build) 2. 插件介绍及使用方法(Tasks and dependencies) 3. 扩展优化(Extend & Optimize Task) 4. 其他插件介绍(Other plug-ins) 5. 匹配规则(Match Files) 6. 注意事项(Attention) 关于Gulp的入门介绍及安装方法,可先去 <