GithubHelp home page GithubHelp logo

es6-with-gulp-build's People

Contributors

chenbin92 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

es6-with-gulp-build's Issues

使用 gulp 搭建前端环境之CommonJs & ES6 模块化(中级篇)

使用 gulp 搭建前端环境之CommonJs & ES6 模块化(中级篇)

1. browserify 简介
2. 编写 CommonJS 模块示例
3. 编写 ES6 Module 模块示例
4. 总结 CommonJs 和 ES6 Module
5. 参考文档

Github示例代码链接

概要:
本篇文章的主要任务是使用 ES6 语法来编写 CommonJs 模块化和使用 ES6 提供的 Module 来实现模块化,跟着下面的步骤一步一步来:

  • 编写 CommonJS 模块示例
  • 编写 ES6 Module 模块示例

1. browserify 简介示例

1.1 browserify 是什么

"Browserify lets you require('modules') in the browser by bundling up all of your dependencies." - Browserify.org

上面的描述是摘自 browserify 官网;用通俗的话讲就是:browserify 是一个浏览器端代码模块化工具,可以处理模块之间的依赖关系,让服务器端的 CommonJS 格式的模块可以运行在浏览器端

1.2 browserify入门

browserify的原理:

处理代码依赖,将模块打包到一起


browserify_ -react_ -


打包为单个文件存在的问题:

  • 暂时用不到的代码也会被打包,体积大,首次加载速度慢
  • 只要一个模块更新,整个文件缓存失效

注:暂时用不到的代码指不同的页面有不同的 JS 文件,不需要在当前页面引用其他页面的代码即为暂时用不到的代码

Browserify的解决方案:
entry point,入口点技术;每个入口点打包一个文件,两个入口点的相同依赖模块单独打包为common.js

1.3 安装配置
  • 安装 browserify
npm install --global browserify
  • 引入 browserify
import  browserify from 'browserify'
  • 基本配置
glup.taks('browserify', function() {
  browserify({
     //先处理依赖,入口文件
     entries: ['./foo.js','./main.js'],
     //进行转化
     transform: []
  })
   .bundle() // 多个文件打包成一个文件
   .pipe(source()) // browserify的输出不能直接用做gulp输入,所以需要source进行处理 
   .pipe(gulp.dest('./'));  
})
1.4 安装一些依赖插件
npm install --save-dev vinyl-source-stream vinyl-buffer gulp-sourcemaps
  • vinyl-source-stream: browserify的输出不能直接用着gulp的输入,vinly-source-stream 主要是做一个转化
  • vinyl-buffer: 用于将vinyl流转化为buffered vinyl文件(gulp-sourcemaps及大部分Gulp插件都需要这种格式)
  • gulp-sourcemaps: Source map就是一个信息文件,里面储存着位置信息。也就是说,转换后的代码的每一个位置,所对应的转换前的位置,便于调试
  • Watchify: 加速 browserify 编译

2. 编写 CommonJS 模块示例

2.1 目录结构
/
|-- dist/
   |-----bundle.js
|-- src/
   |-----foo.js
   |-----main.js
|--gulpfile.babel.js
|--package.json
2.2 新建两个模块文件 foo.js, main.js
$ touch foo.js main.js
2.3 让我使用 CommonJs 规范来写一些代码

CommonJS 规范是为了解决 JavaScript 的作用域问题而定义的模块形式,可以使每个模块在它自身的命名空间中执行。该规范的主要内容是,模块必须通过 module.exports 导出对外的变量或接口,通过 require() 来导入其他模块的输出到当前模块作用域中。

// foo.js
// 定义foo.js模块,通过 module.exports 导出对外的变量或接口
let variable = 8;
let sum = (a, b = 6) => (a + b);
let square = (b) => {
    return b * b;
};
module.exports.variable = variable;
module.exports.sum = sum;
module.exports.square = square;
// mian.js
// 通过 require() 来导入 foo.js 模块
var bar = require('./foo')
console.log(bar);  // Object
console.log(bar.variable); // 8
console.log(bar.sum(1)); // 7
console.log(bar.square(5)); // 25

上面我们使用 ES6 的语法写了两个模块,分别是 foo.jsmain.js; 在 foo.js 中通过 module.exports 导出对外的变量或接口;在 main.js 中通过 require() 来导入 foo.js 模块,那我们就可以在 mian.js 模块中使用 foo.js 中的变量和接口了。这就是一个最基本的 CommonJs 示例了。

2.4 配置 browserify

通过第一小节的学习,我们知道要在浏览器中运行 CommonJs 风格的模块代码,就需要借助 browserify 来作为转换工具,下面我们在 gulp.babel.js 中来配置 browserify

// set browserify task
gulp.task('browserify',()=> {
    browserify({
        entries: ['src/js/main.js','src/js/foo.js'],
        debug: true, // 告知Browserify在运行同时生成内联sourcemap用于调试
    })
        .transform("babelify", {presets: ["es2015"]})
        .bundle()
        .pipe(source('bundle.js'))
        .pipe(buffer()) // 缓存文件内容
        .pipe(sourcemaps.init({loadMaps: true})) // 从 browserify 文件载入 map
        .pipe(sourcemaps.write('.')) // 写入 .map 文件
        .pipe(gulp.dest('dist/js'))
        .pipe(notify({ message: 'browserify task complete' }));
})
2.5 运行
gulp-browserify

screen shot 2015-12-09 at 11 32 07 pm

##### 2.6 打开浏览器,查看运行结果(见上面main.js文件的注释) ## 3. 编写 ES6 Module 模块示例

上面的代码主要是 CommonJs 模块化的写法,我们再来看看最近火热的 ES6 提供的 Module;让我们使用 ES6 Module 来改写上面的代码:

// foo.js
// 定义foo.js模块,通过 exports 导出对外的变量或接口
let variable = 8;
let sum = (a, b = 6) => (a + b);
let square = (b) => {
    return b * b;
};
export { variable, sum, square };
// main.js
// 测试一:
// 通过 import 来导入 foo.js 模块
import {variable, sum, square} from './foo';
console.log(variable); // 8
console.log(sum(1)); // 7
console.log(square(5)); // 25

// 测试二:
// 直接引用整个 foo 模块
import bar from './foo';
console.log(bar); // 输出值是undefined,后面做解释

// 测试三:
// 通过 ES6 的语法加载整个 foo模块
import * as bar from './foo'
console.log(bar); // Object

4. 总结 CommonJs 和 ES6 Module

4.1 CommonJs
  • 根据 CommonJS 规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在一个文件定义的变量(包括函数和类),都是私有的,对其他文件是不可见的
  • 通过 module.exports 对象,定义对外接口,其他文件加载该模块,实际上就是读取 module.exports 变量
  • 通过 require 命令加载模块文件,然后返回该模块的exports对象
4.2 ES6 Module
  • 通过 export 命令用于规定模块的对外接口
  • 通过 import 命令用于加载其他模块提供的功能
4.3 ES6 Module 与 CommonJs 的区别
  • 在ES6中使用 import 取代 require
  • 在ES6中使用 export 取代 module.exports
  • ES6 在编译时就能确定模块的依赖关系,以及输入和输出的变量,而 CommonJs 只能在运行时确定模块的依赖关系以及输入和输出的变量。
    • 运行时加载: CommonJS 模块就是对象;即在输入时是先加载整个模块,生成一个对象,然后再从这个对象上面读取方法,这种加载称为“运行时加载”
    • 编译时加载: ES6 模块不是对象,而是通过 export 命令显式指定输出的代码,输入时采用静态命令的形式。即在输入时可以指定加载某个输出值,而不是加载整个模块,这种加载称为“编译时加载”

注:上面提到 ES6 加载模块时是采用指定加载某个输出值的形式,如果你要想加载整个模块,你可以这么做:import * as customName from './moduleFileName';

5. 参考文档

使用 gulp 搭建前端环境之 ionic 项目实践总结

使用 gulp 搭建前端环境之 ionic 项目实践总结

3.1 前言
3.2 angular 目录结构简介
3.3 ionic 目录结构简介
3.4 重构 ionic 目录结构
       3.4.1 区分 SRC 和 WWW
       3.4.2 切换 Development、Staging、Production环境
3.5 gulp 配置详解
    3.6 升级到 ionic2 
    3.7 参考文档

详细步骤及示例请移步至 ionic quickstarter with gulp

3.1 前言

我们常常会花很多时间去写代码,在项目的早期阶段,很多人倾向忽视目录结构的组织;在短期时间内,这可以让开发人员快速的编写代码,但从长远来看会影响代码的可维护性;有时候或许会想到去 github 或者 google 去搜索,比如 angular-seed等等,一些框架已经提供了最佳实践的项目结构。下面将主要分享团队在 angular 项目和 ionic 项目结构上的实践过程;如有不恰当之处,欢迎指正。

3.2 angular 目录结构简介

ionic 是基于 angular 的一套移动框架,我们需要先来看看 angular 的目录结构:

按文件类型分类(Sort By Type)

许多 AngularJS 教程提供了类似于下面的项目目录结构,这是一个非常典型的应用程序结构;在表面看起来,非常类似于 MVC 框架的目录结构,分为 controllers目录、views目录,以及第三方的JavaScript库的目录。

当你只有少数的视图和控制器,这看起来是非常的好。事实上,它只适合我们对照教程编写示例代码或较小的应用程序。这种结构使得初学者很容易理解其中的概念。

但是当你开始向应用程序添加复杂的功能,这种组织方式很快会遇到一些问题,一旦你有10多个控制器,视图和指令文件,你就需要滚动目录树找到所需文件,随着应用程序的增大,如何维护就会成为一个问题:


www/
|
|- app/
|   |- controllers/
|   |     |- mainController.js
|   |     |- otherController.js
|   |
|   |- directives/
|   |     |- ButtonDirective.js
|   |     |- otherDirective.js
|   |
|   |- services/
|   |     |- userService.js
|   |     |- itemService.js
|   |
|   |- js/
|   |   |- bootstrap.js
|   |   |- jquery.js
|   |
|   |- app.js
|   |
|- views/
|   |- mainView.html
|   |- otherView.html
|   |- index.html
|   |
|- css/
|   |- style.scss
|   |
|- img/
|     |- logo.png

按照功能分类(Sort by Feature)

src/
 |app/
 |  |- admin/
 |  |     |- acount/
 |  |     |- users/
 |  |     |- admin.js
 |  |- dashboard/
 |  |     |- dashboard.js
 |  |     |- dashboard.tpl.html
 |  |- app.js
 |-assets/
 |   |- img/
 |   |- css/
 |   |- font/
 |-common/
 |   |- directives/
 |   |- resources/
 |   |- services/
 |-sass/
 |   |- main.scss
 |   |- variables.scss
 |-index.html
 vendor/
 |- angular
 |- boootstrap
 |- jquery

这种结构把不同的业务功能拆分为独立的文件,条理清晰,但是仍有一定的局限性。最大的问题是同一个业务功能的代码分布在 controllers, models, services 三个不同目录下,要从中挑选出相对应的文件,建立起代码关联,还是有些麻烦。在项目结构二的改进下,于是便有了第三种项目结构,按照功能模块划分目录结构,或许更为合理一些:

按照模块分类(Structuring for Modules)

让我们得到最佳实践和你应该做什么来构建可伸缩和可维护的AngularJS应用,你的同事会爱死你的。理想 AngularJS 程序结构应该模块化到非常具体的功能;我们应该要利用好AngularJS的特性进一步划分我们的应用程序。下面看一个示例目录结构:

/
|
|- src/
|
|    |
|    |- app/
|    |    |- home/
|    |    |    |
|    |    |    |- home.module.js
|    |    |    |- home.controller.js
|    |    |    |- home.directive.js
|    |    |    |- ($feature.$type.js)
|    |    |    |- home.html
|    |    |    |- home.scss
|    |    |
|    |    |- config/
|    |    |    |- config.default.json
|    |    |    |- config.development.json
|    |    |    |- config.production.json
|    |    |    |- config.js
|    |    |
|    |    |- app.js
|    |    |- app.routes.js
|    |    |- app.services.js
|    |    |- app.templates.js
|    |    |
|    |- css/
|    |    |- scss/
|    |    |    |- ionic.app.scss (index file)
|    |    |- ionic.app.css (all css will be compiled into this file)
|    |    |
|    |- img/
|    |    |
|    |- lib/
|    |    |- angular/
|    |    |- angular-resource
|    |    |- ionic
|    |- shared/ (common components cross projects)
|    |    |- canvasClock/
|    |    |- calendar/
|    |    |- constants/
|    |- index.html

参考:

3.3 ionic 目录结构简介

最近陆陆续续做过一些基于 ionic 的 hybird app,遇到过一些问题,踩过一些坑;有开发过 ionic 经验的人都知道,我们只需要使用 ionic start ProjectName 就可以生成一个 ionic 的模板项目结构:

ionic project structure

ionic 默认开发环境是在 www目录,因此我们的关注点只需要聚焦在 www目录即可,观察上面的项目结构,我们可以发现与在分析 angular 目录时的按文件类型分类的目录结构是类似的

另外:ionic 默认只提供了基于 gulp 的 sass 编译,使用 bower 来安装库依赖,除此之外并没有其他的自动化构建流程,如常见的代码合并压缩,图片压缩,分环境开发等等;因此我们需要重构 ionic 默认的目录结构,以此来完成适合大型应用的目录

有了上面 angular 和 ionic 目录的简单介绍,我们知道 ionic 默认的项目结构可能更适合一般的项目架构,如果我们想更好的管理 ionic 项目,我们需要对它进行重构和更多的自动化构建过程

3.4 重构 ionic 目录结构

我们先来看看重构后的项目目录结构,然后再来分析它所遵循的规范:

/
|
|- src/
|
|    |
|    |- app/
|    |    |- home/
|    |    |    |
|    |    |    |- home.module.js
|    |    |    |- home.controller.js
|    |    |    |- home.directive.js
|    |    |    |- ($feature.$type.js)
|    |    |    |- home.html
|    |    |    |- home.scss
|    |    |
|    |    |- config/
|    |    |    |- config.default.json
|    |    |    |- config.development.json
|    |    |    |- config.production.json
|    |    |    |- config.js
|    |    |
|    |    |- app.js
|    |    |- app.routes.js
|    |    |- app.services.js
|    |    |- app.templates.js
|    |    |
|    |- css/
|    |    |- scss/
|    |    |    |- ionic.app.scss (index file)
|    |    |- ionic.app.css (all css will be compiled into this file)
|    |    |
|    |- img/
|    |    |
|    |- lib/
|    |    |- angular/
|    |    |- angular-resource
|    |    |- ionic
|    |- shared/ (common components cross projects)
|    |    |- canvasClock/
|    |    |- calendar/
|    |    |- constants/
|    |- index.html
|
|- www
  • app : components using for the app
  • css : common stylesheets, using scss
  • img : common images
  • lib : thrid-party libraries managed by bower
  • shared : common components cross projects
  • www : compile the source code for the production environment

从上面的目录结构可以看到,现在的目录结构有点类似于我们在分析 angular 项目时的按照模块来分类的项目结构;这种组织方式适合编写大型的应用程序,它不同于我们使用 ionic start projectName 初始化的项目目录;

ionic 默认的目录将所有的routes, controllers都放在一个文件夹,将所有的html 模板文件放在一个文件夹;

相反的,我们选择使用模块来管理组织文件,每个模块是在自己的目录包含 JavaScript(控制器)和HTML(模板),css,image;即每个功能点都是一个小的模块,这使它更容易保持一个大型应用程序组织和维护。

3.4.1 区分 srcwww 目录

新增加 src 文件夹,项目的源代码(HTML、CSS、JavaScript)位于 src 目录下面而不是位于默认的 www 目录下

ionic serve 默认是读取 www 目录下文件启动本地静态服务器,我们通过使用 gulp 构建来将 src 的代码映射到 www 目录下

  • development 当你想切换到开发环境在浏览器上运行时,只需要执行ionic serve
  • production 当你想切换到生产模式在设备上设备时,只需执行ionic build --env production

3.4.2. 模块区分原则

一般原则: ONE DIRECTORY == ONE MODULE (and one subdirectory == 1 sub module).

模块的定义需要根据项目而定,切分的粒度也需要视情况而定,例如我们可以将 login切换为一个模块,所有有关login模块的html,css,js,img都放在login模块目录下:

这里引用前端农民工张云龙大神的一张图片作为说明

moduleExample

推荐阅读: 前端工程——基础篇

3.4.3. 切换development,staging和production环境

当你从 ionic-quickStart clone项目之后,默认的是development环境,你需要开起两个终端来分别执行 gulp buildionic serve来运行项目:

# switch to development mode
$ gulp build # same as running `gulp build --env development`

# run local serve
$ ionic serve

当你需要切换到staging环境,即常说的预发布环境(压缩源代码,API路径替换等等),你只需要执行gulp build --env staging来自动化构建你的项目L

# switch to staging mode
$ gulp build --env staging

当你需要切换到production环境,即常说的生产环境(与staging环境只有API路径不同),你只需要执行gulp build --env production来自动化构建你的项目:

// switch to production mode
$ gulp build --env production

3.5 gulp 配置详解

更改 ionic 默认的项目结构后,我们需要基于gulp来构建更完善的流程,先来看看整个的流程图:

gulp build process

gulp build process

gulp build task

gulp build task

Using gulp switch different environments

GIF demo


构建流程详解:

  1. 在开发模式下:需要默认将 SRC 下的文件复制到 WWW 目录下,并且实时监听 SRC 文件的改动映射到 www(因为 ionic serve 默认会读取 www 目录下的文件启动本地服务);开发模式主要的 gulp 任务是监听 html, css, JS 的改动,sass 的编译,实时刷新,stylelint,JSLint,文件替换和 API 路径配置;
  2. 在预生产模式下:首先需要清除掉 WWW 目录下的所有文件,然后重新从 SRC 编译代码到WWW 目录下,这个过程主要的 gulp 任务是:清除文件,HTML 模板合并缓存,图片压缩,CSS 合并压缩,JS 合并压缩;
  3. 在生产模式下: 生产模式和预生产模式除了 API PATH 配置不一样,其它的gulp任务都是一样;

详细步骤及示例请移步至ionic-quickstarter-with-gulp

3.6 升级到 ionic2

ionic2 现在虽然还未发布,但是我们可以从官方文档下载有关 ionic2 的相应示例,对比发现,我们这次基于gulp的构建结构竟然与 ionic2 有异曲同工之妙(吹嘘😄),ionic2 主要分为appwww目录,以此来区分不同的开发模式,组件化等等,基于 Webpack 构建,流程更加完善,值得期待!

ionic2 目录结构

 |-www/
    |
    |--Home/
    |--|-HomeCtrl.js
    |--|-Home.html
    |
    |--Detail/
    |--|-DetailCtrl.js
    |--|-Detail.html
    |
    |-index.html
    |-app.js

3.7 参考文档

使用 gulp 搭建前端环境(入门篇)

使用 gulp 搭建前端环境

1. gulp 入门基础
2. 配置常用插件
3. ES6 代码转化
4. 完整演示示例
5. 参考文档

gulp 入门基础

1.全局安装 gulp
$ npm install --global gulp
2.作为项目的开发依赖 (devDependencies)
$ npm install --save-dev gulp
3.在项目根目录下面创建一个名为 gulpfile.js 的文件:
$ touch gulpfile.js
// 配置 gulp 的相关任务
4.运行 gulp:
$ gulp

配置常用插件

下面的步骤从零开始动手搭建环境

1.检查你的 node 版本和 gulp 版本
node -v 
//  => v4.0.0
gulp -v
//  => CLI version 3.9.0
//  => Local version 3.9.0
2.安装常用插件

初始化项目目录

 $ mkdir ES6-with-gulp-babe && cd ES6-with-gulp-babe && git init && npm init

注: 使用 npm init 创建一个 package.json 存储依赖关系等配置信息

安装依赖插件

  $ npm install --save-dev gulp gulp-sass gulp-autoprefixer browser-sync gulp-notify

上述命名依次安装了 gulpgulp-sassgulp-autoprefixerbrowser-syncgulp-notify 等常用插件,其中:

  • gulp-sass 用于将 Sass 文件编译为 CSS 文件
  • gulp-autoprefixer 根据浏览器版本自动处理添加浏览器前缀
  • browser-sync 能让浏览器实时、快速响应文件更改(html、js、css、sass、less等)并自动刷新页面
  • gulp-notify 用于任务提醒
3.创建 gulp 的配置文件 gulpfile.js

browser-sync 为例来配置 gulpfile.js 文件

// 加载插件
var gulp        = require('gulp');
var browserSync = require('browser-sync').create();

// 静态服务器 + 监听 scss/html 文件
gulp.task('serve', ['sass'], function() {

    browserSync.init({
        server: "./app"
    });

    gulp.watch("app/scss/*.scss", ['sass']);
    gulp.watch("app/*.html").on('change', browserSync.reload;);
});

4. Browsersync可以同时在PC、平板、手机等设备下进项调试

sync-demo1

sync-demo2

ES6 代码转化

使用 ES6 的语法重写 gulpfile.js, 在最新的 gulp 3.9 版本上,开发者可以使用 ES6 语法来编写配置文件,但是需要安装 babel 来转化 ES6 代码

第一步:安装 babel

 npm install babel-core babel-preset-es2015 --save-dev

第二步:在根目录下创建 .babelrc 配置文件

touch .babelrc

并添加以下内容:

{
  "presets": ["es2015"]
}

注:.babelrcbabel 的配置文件,保存在项目的根目录下,其中presets用于设置开启的语法特性集合,详细介绍可参考官方文档:https://babeljs.io/docs/usage/babelrc/http://babeljs.io/docs/plugins/#presets

第三步:将 gulpfile.js 重名为 gulpfile.babel.js

 mv "gulpfile.js" "gulpfile.babel.js"

第四步:现在我们就可以使用ES6的语法重写 gulp 的配置文件

'use strict';

import babel from 'gulp-babel';

gulp.task('babel',() => {
  gulp.src('src/app.js')
    .pipe(babel())
    .pipe(gulp.dest('dist'))
    .pipe(notify({ message: 'babel task complete' }));
})

完整演示示例

1.安装

  • Clone the repo
  • npm install -g gulp to install Gulp globally.
  • npm install to resolve project dependencies.

2.使用

  • Run gulp

参考文档

  1. Gulp 开发教程
  2. Gulp:任务自动管理工具
  3. Using ES6 with gulp
  4. Browsersync
  5. Gulp getting started

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.