搁浅被注册了

图样 图森破 、

@搁浅被注册了7年前

07/4
15:42
Gulp

字蛛,现已加入Gulp豪华午餐~

字蛛(fontspider)是什么?用过 iconfont 我们知道图标也可以使用字体来绘制,各式各样的中文字体理所应当的也可以嵌入到Web上来。然而,相比英文字体,中文字体显然太过庞大,动辄几M的大小挂到页面上显然不现实。字蛛就应运而生,只保留你使用的文字,没有用到的字通通删掉,从而生成精简压缩的字体文件。

遇到特殊中文不想再切图片了?字蛛,让网页自由引入中文字体成为可能。更多详情请戳 → 字蛛官网

字蛛的Gulp插件现已基本完善,结合前面的 Gulp自动化教程 ,把字蛛(fontspider)整合到你的 gulpfile.js 中。

1. 给项目安装 gulp-font-spider

npm install gulp-font-spider --save-dev

2. 在 gulpfile.js 中引入 gulp-font-spider 插件,并修改原有任务

fontSpider = require( 'gulp-font-spider')
// fontspider
gulp.task('fontspider', ['sass', 'css'], function () {
  gulp.start('html');
});

// html
gulp.task('html', function () {
  gulp.src('src/font/**/*')
    .pipe(gulp.dest('dist/font'))
  return gulp.src('src/*.html')
    .pipe(fileinclude())
    .pipe(rev())
    .pipe(gulp.dest('dist/'))
    .pipe(fontSpider())
});

3. 调整目录结构

源码目录增加 src/font 用于存放未修改字体

└── src / 源码目录
  ├── build /   .html 组件
  ├── sass /     .scss.sass 文件
  ├── css /       .css 文件
  ├── js /         .js 文件
  ├── font/      .ttf 等字体文件
  └── img / 图片
└── dist / 输出目录
└── package.json
└── gulpfile.js

4. 在 CSS 和 HTML 中的正确打开方式

下面的代码声明一个 “pinghei” 的 @font-face ,使用 .test 类标识。你也可以创建多个符合CSS命名规范的自定义 @font-face。
则在 HTML 中拥有 .test 类的元素的文本将被标识,生成的精简字体将只包含被标识的文字。

/*声明 WebFont*/
@font-face {
  font-family: 'pinghei';
  src: url('../font/pinghei.eot');
  src:
    url('../font/pinghei.eot?#font-spider') format('embedded-opentype'),
    url('../font/pinghei.woff') format('woff'),
    url('../font/pinghei.ttf') format('truetype'),
    url('../font/pinghei.svg') format('svg');
  font-weight: normal;
  font-style: normal;
}

/*使用选择器指定字体*/
.test {
  font-family: 'pinghei';
}

5. 完整的 gulpfile.js 示例

/*!
* gulp
* $ npm install gulp del gulp-cached gulp-uglify gulp-rename gulp-concat gulp-notify gulp-filter gulp-jshint gulp-ruby-sass gulp-rev-append gulp-cssnano gulp-replace gulp-imagemin browser-sync gulp-font-spider gulp-file-include gulp-autoprefixer --save-dev
*/

// Load plugins
var gulp = require('gulp'), // 必须先引入gulp插件
  del = require('del'), // 文件删除
  cached = require('gulp-cached'), // 缓存当前任务中的文件,只让已修改的文件通过管道
  uglify = require('gulp-uglify'), // js 压缩
  rename = require('gulp-rename'), // 重命名
  concat = require('gulp-concat'), // 合并文件
  notify = require('gulp-notify'), // 相当于 console.log()
  filter = require('gulp-filter'), // 过滤筛选指定文件
  jshint = require('gulp-jshint'), // js 语法校验
  sass = require('gulp-ruby-sass'), // sass 编译
  rev = require('gulp-rev-append'), // 插入文件指纹(MD5)
  cssnano = require('gulp-cssnano'), // CSS 压缩
  replace = require('gulp-replace'), // 批量替换字符串
  imagemin = require('gulp-imagemin'), // 图片优化
  browserSync = require('browser-sync'), // 保存自动刷新
  fontSpider = require('gulp-font-spider'), // 字蛛,让Web中文字体成为可能
  fileinclude = require('gulp-file-include'), // 可以 include html 文件
  autoprefixer = require('gulp-autoprefixer'); // 添加 CSS 浏览器前缀

// sass
gulp.task('sass', function () {
  return sass('src/sass/**/*.scss', { style: 'expanded' }) // 传入 sass 目录及子目录下的所有 .scss 文件生成文件流通过管道并设置输出格式
    .pipe(cached('sass')) // 缓存传入文件,只让已修改的文件通过管道(第一次执行是全部通过,因为还没有记录缓存)
    .pipe(autoprefixer('last 6 version')) // 添加 CSS 浏览器前缀,兼容最新的5个版本
    .pipe(gulp.dest('dist/css')) // 输出到 dist/css 目录下(不影响此时管道里的文件流)
    .pipe(rename({ suffix: '.min' })) // 对管道里的文件流添加 .min 的重命名
    .pipe(cssnano()) // 压缩 CSS
    .pipe(gulp.dest('dist/css')) // 输出到 dist/css 目录下,此时每个文件都有压缩(*.min.css)和未压缩(*.css)两个版本
});

// css (拷贝 *.min.css,常规 CSS 则输出压缩与未压缩两个版本)
gulp.task('css', function () {
  return gulp.src('src/css/**/*.css')
    .pipe(cached('css'))
    .pipe(gulp.dest('dist/css')) // 把管道里的所有文件输出到 dist/css 目录
    .pipe(filter(['**/*', '!**/*.min.css'])) // 筛选出管道中的非 *.min.css 文件
    .pipe(autoprefixer('last 6 version'))
    .pipe(gulp.dest('dist/css')) // 把处理过的 css 输出到 dist/css 目录
    .pipe(rename({ suffix: '.min' }))
    .pipe(cssnano())
    .pipe(gulp.dest('dist/css'))
});

// styleReload (结合 watch 任务,无刷新CSS注入)
gulp.task('styleReload', ['sass', 'css'], function () {
  return gulp.src(['dist/css/**/*.css'])
    .pipe(cached('style'))
    .pipe(browserSync.reload({ stream: true })); // 使用无刷新 browserSync 注入 CSS
});

// script (拷贝 *.min.js,常规 js 则输出压缩与未压缩两个版本)
gulp.task('script', function () {
  return gulp.src(['src/js/**/*.js'])
    .pipe(cached('script'))
    .pipe(gulp.dest('dist/js'))
    .pipe(filter(['**/*', '!**/*.min.js'])) // 筛选出管道中的非 *.min.js 文件
    // .pipe(jshint('.jshintrc')) // js的校验与合并,根据需要开启
    // .pipe(jshint.reporter('default'))
    // .pipe(concat('main.js'))
    // .pipe(gulp.dest('dist/js'))
    .pipe(rename({ suffix: '.min' }))
    .pipe(uglify())
    .pipe(gulp.dest('dist/js'))
});

// image
gulp.task('image', function () {
  return gulp.src('src/img/**/*.{jpg,jpeg,png,gif}')
    .pipe(cached('image'))
    .pipe(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true, multipass: true }))
    // 取值范围:0-7(优化等级),是否无损压缩jpg图片,是否隔行扫描gif进行渲染,是否多次优化svg直到完全优化
    .pipe(gulp.dest('dist/img'))
});

// fontspider
gulp.task('fontspider', ['sass', 'css'], function () {
  gulp.start('html');
});

// html 编译 html 文件并复制字体
gulp.task('html', function () {
  gulp.src('src/font/**/*')
    .pipe(gulp.dest('dist/font')) // 将预处理字体复制到 dist/font
  return gulp.src('src/*.html')
    .pipe(fileinclude()) // include html
    .pipe(rev()) // 生成并插入 MD5
    .pipe(gulp.dest('dist/'))
    .pipe(fontSpider()) // 在文档流中使用 font-spider 匹配文字
});

// clean 清空 dist 目录
gulp.task('clean', function () {
  return del('dist/**/*');
});

// build,关连执行全部编译任务
gulp.task('build', ['sass', 'css', 'script', 'image'], function () {
  gulp.start('html');
});

// init 任务,重新执行全部编译
gulp.task('init', ['clean'], function () {
  gulp.start('build');
});

// default 默认任务,执行全部编译并启动监听
gulp.task('default', ['init'], function () {
  gulp.start('watch');
});

// watch 开启本地服务器并监听
gulp.task('watch', function () {
  browserSync.init({
    server: {
      baseDir: 'dist' // 在 dist 目录下启动本地服务器环境,自动启动默认浏览器
    },
    open: 'external' // 使用本机IP地址打开浏览器,方便局域网调试
  });

  // 监控 SASS 文件,有变动则执行CSS注入
  gulp.watch('src/sass/**/*.scss', ['styleReload']);
  // 监控 CSS 文件,有变动则执行CSS注入
  gulp.watch('src/css/**/*.css', ['styleReload']);
  // 监控 js 文件,有变动则执行 script 任务并自动刷新
  gulp.watch('src/js/**/*.js', ['script', browserSync.reload]);
  // 监控图片文件,有变动则执行 image 任务并自动刷新
  gulp.watch('src/img/**/*', ['image', browserSync.reload]);
  // 监控 html 文件,有变动则执行 html 任务并自动刷新
  gulp.watch('src/**/*.html', ['html', browserSync.reload]);

});

6. 使用场景及浏览器兼容性参考

使用场景限制:

  • 仅支持固定的文本与样式,不支持 javascript 动态插入的元素与样式
  • .otf 字体需要转换成 .ttf 才能被压缩
  • 仅支持 utf-8 编码的 HTML 与 CSS 文件
  • CSS content 属性只支持普通文本,不支持属性、计数器等特性

字体兼容性参考:http://caniuse.com/#feat=fontface

7.  正确的打开方式及待解决问题

单独使用 gulp fontspider 无法完成字蛛的所有流程,因为还需要复制字体到 dist/font ,请使用 gulp html 任务替代。其中的原因是没找到合适的方案定义输出字体文件位置,只能妥协的使用复制的方式附加在 html 任务里实现(参考html任务代码),反而实现了在 watch 任务里使用 fontspider ,达成了意外的成就2333

————————————- 16.08.18 更新 ———————————-

现已可以使用 gulp fontspider 命令单独执行字蛛更新。经过多次测试应该是没什么问题了~~ 大概

————————————- 16.12.12 更新 ———————————-

整合任务到到 default 任务,感谢 @亿林
 

字蛛,现已加入Gulp豪华午餐~

  1. 亿林
    UnknownUnknownUnknownUnknown

    提个小issue,watch任务是不是应该加入到default任务里面,这样运行gulp时就能实时自动重整,不然还要手动启动gulp watchgulp.task(‘default’, [‘clean’], function() { gulp.start([‘build’, ‘watch’]);});

    回复