一开始我们这样写js

<script type="text/javascript">
function a(){
  console.log('a init');
}
function b(){
  console.log('b init');
  a();
}
</script>

随着功能越来越多,我们开始把js分离,使用单独的js文件来写,然后使用下面的方式引入js

<script src="a.js" type="text/javascript" charset="utf-8"></script>
<script src="b.js" type="text/javascript" charset="utf-8"></script>

这种方式有几个缺陷:

1,不能体现他们之间的依赖关系

2,文件越多请求越多,请求多会拖慢网页打开速度

3,代码写起来不爽

有没有一种方式既可以愉快的写又可以很好的组织代码呢,那就是模块化编程。

目前有两种js编码规范来解决上述问题:AMD(异步模块定义)和CMD(通用模块定义),

根据这两种规范实现的js加载器分别有:

AMD:require.js

CMD:Sea.js

笔者使用的是require.js。

下面展示一下如何用require.js来进行模块化开发,

先看一下目录结构

使用require.js怎么来加载呢,首先在网页中引入require.js 然后在script标签中增加一个 自定义属性 data-main="main.js" 页面加载完毕后require.js会根据这个属性去找main.js 然后开始执行,main.js是入口文件

<script src="require.js" defer async data-main="main.js" type="text/javascript" charset="utf-8"></script>

下面是入口文件main.js

requirejs.config({
baseUrl: 'js/' //模块文件所在位置
});
require(['b'],function(b){
b.init();
});

require.js里有两个方法很重要一个是require一个是define 前者用来引入模块,后者用来定义模块

在main.js中用 requirejs.config 配置好模块们所在位置之后就可以使用 require方法来使用他们了

a.js和b.js是两个模块 由于require.js会自动补全所以我们引用的时候不必书写完整的文件名称a.js,只需要写文件名a就行了

a.js

define(function(){
return {
init:function(){
console.log("a init")
}
}
});

b.js

define(['a'],function(a){
return {
init:function(){
console.log("b init")
a.init();
}
}
});

b依赖a所以在定义b的时候 需要在define的第一个参数中引入a ,define第一个参数是数组类型,如果引入多个模块那么就像这样:define(['a','a1','a2'],function(a,a1,a2){})

执行后

是不是很简单,简简单单几行代码就拥抱了模块化编程是不是很激动

现在激动还为时过早,模块化编程我们是用上了但是还没有解决第二个问题,就是请求数,现在还是一个模块一个js文件

现在要做的就是把他们合并,合并成一个js文件,

是时候请出第二个主角了, 没错就是Gulp 。整天在网上看自动化构建 啥是自动化啥是构建呀

用在我们这个例子里就是 自动合并,比如我添加或者修改了模块 Gulp会自动把新代码合并,是不是很酷 。在gulp里这些操作称为任务,通过gulp的watch方法来监控文件,达到文件一变动,任务就执行的目的,这就是自动化构建。

Gulp提供了丰富的插件,Gulp依赖Node.js环境所以需要先安装node.js,以下说的是windows上的操作步骤

首先下载 node.js 下载地址:http://nodejs.cn/download/

安装好后进入根目录 按住shift 点击鼠标右键 打开命令行

使用node.js自带的npm包管理工具安装gulp

这里提一下,如果直接装会比较慢,推荐使用淘宝的npm镜像:http://npm.taobao.org/

npm install -g cnpm --registry=https://registry.npm.taobao.org
//装完之后就可以用cnpm 替代npm 速度飞快

cnpm i gulp -g  

安装npm包可以选择是安装到项目里还是安装到全局 ,下面我们安装最重要的一个npm模块gulp-requirejs-optimize 这个模块基于requre.js提供的打包工具https://github.com/requirejs/r.js

cnpm i gulp-requirejs-optimize -D

//我们用了简写的命令 上面的命令等同于 cnpm install gulp-requirejs-optimize --save-dev  后面的--save-dev意思是

把我们装的这个模块加入到Npm的包配置清单里 这个清单是个配置文件叫做 package.json

如果一个一个装显得有些繁琐, 有没有一键安装,答案是有的。

上面我们提到了package.json, 没错我们可以利用这个文件实现一个命令安装所有依赖模块

{
"name": "",
"description": "",
"version": "1.0.0",
"author": "maxiao",
"private": true,
"scripts": {
},
"dependencies": {
},
"devDependencies": {"gulp": "^3.9.1",
"gulp-bom": "^1.0.0","gulp-rename": "^1.2.2",
"gulp-requirejs": "^1.0.0-rc2",
"gulp-requirejs-optimize": "^1.2.0",
"gulp-rev": "^8.0.0",
"gulp-rev-collector": "^1.2.2",
"gulp-sequence": "^0.4.6", }
}

我们把这个文件放到根目录下然后在命令行里执行 cnpm install  npm会自动把里面列的所有模块都装上

这里提到的模块是node.js里的模块而非我们前端定义的那些模块 ,唯一的区别是一个在node.js里执行一个在浏览器端执行 ,如果对js的服务端编程感兴趣的话可以去了解一下node 这里就不多聊了。

当所有gulp依赖的模块都安装好之后就可以编写我们的gulp任务脚本了 ,没错这个脚本是个js文件叫做gulpfile.js

下面是gulpfile.js里的内容,是不是很熟悉

var gulp = require('gulp');// 引入组件
var
minifycss = require('gulp-minify-css'),//css压缩
uglify = require('gulp-uglify'),//js压缩
requirejsOptimize = require('gulp-requirejs-optimize');
concat = require('gulp-concat'),//文件合并
rename = require('gulp-rename'),//文件更名
rev = require('gulp-rev'),//给文件名添加版本号
del = require('del'),//删除就版本
bom = require('gulp-bom'),//添加bom防止中文乱码
obfuscate = require('gulp-obfuscate'),
revCollector = require('gulp-rev-collector'),//路径替换
gulpSequence = require('gulp-sequence'), //按顺序执行任务
;//提示信息
var newVersion = function () {
var uuid = require('node-uuid');
return uuid.v1().slice(0, 8)
}
/***************************************************************************************************************JS*/
//清理
gulp.task('clearjs', function (cb) {
return del('dest/livecontent/livecommon/app/*.js', cb);
}); gulp.task("requirejs_pipe", function () {
return gulp.src('main.js')
.pipe(requirejsOptimize(function (file) {
return {
name: 'main',
optimize: 'uglify2',
//useStrict: true,
baseUrl: '/', };
}))
.pipe(rev())
.pipe(gulp.dest('dest/'))
.pipe(rev.manifest({
merge: true
}))
.pipe(gulp.dest('')); });
//更改版本号
gulp.task('renamejs', function () {
return gulp.src('main.js')
.pipe(rev())
.pipe(gulp.dest('dest/'))
.pipe(rev.manifest({
merge: true
}))
.pipe(gulp.dest(''));
});
//更改引用
gulp.task('usenewjs', function () {
return gulp.src(['rev-manifest.json', 'index.html']) //- 读取 rev-manifest.json 文件以及需要进行css名替换的文件
.pipe(revCollector({
replaceReved: true
}))
.pipe(bom())
//- 执行文件内css名的替换
.pipe(gulp.dest('dest/js/'));
});
// 默认任务
gulp.task('default', function () {
gulpSequence('clearjs',
'requirejs_pipe','usenewjs'
)(function (err) {
if (err) console.log(err)
})
// Watch .js files
gulp.watch(['js/*.js'], function () {
gulpSequence('clearjs', 'requirejs_pipe', 'usenewjs')(function (err) {
if (err) console.log(err)
})
}); });

写好后在命令行里输入:gulp 然后回车

gulp就会一直监控js目录下的文件变化了,一有改动就会生成新的文件写入到dest目录下

里面用到了几个我没提到的模块比如 给合并后的文件加版本号的,控制任务顺序执行的,删除文件,防止文件乱码的,这都是笔者爬坑过程中为了解决问题一个一个找的啊 真良心推荐 每个都会用到

我们项目中的代码只有index.html requre.js,main.js,a.js,b.js  。 node.js,npm ,gulp只是我们的用到的工具。

es6的到来前端工具百花齐放,学好js再使用他们就会感觉很顺手事半功倍

玩转JS系列之代码加载篇的更多相关文章

  1. 解决代码加载慢,以至于乱码—————VUE

    vue.js解决开始代码加载,以至于乱码 vue.js通过几行代码可以解决这个问题 css: [v-cloak] { display: none; } html: <div id="a ...

  2. 如何使用 require.js ,实现js文件的异步加载,避免网页失去响应,管理模块之间的依赖性,便于代码的编写和维护。

    一.为什么要用require.js? 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了.后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载.下面的网页代 ...

  3. html文件在head标签中引入js地址和直接写js代码,所用时间是不同的,因为引入js地址,文件加载的时候需要通过通讯协议去解析地址,读取外部文件

    html文件在head标签中引入js地址和直接写js代码,所用时间是不同的,因为引入js地址,文件加载的时候需要通过通讯协议去解析地址,读取外部文件

  4. JS实现图片预加载无需等待

    网站开发时经常需要在某个页面需要实现对大量图片的浏览;用javascript来实现一个图片浏览器,让用户无需等待过长的时间就能看到其他图片 网站开发时经常需要在某个页面需要实现对大量图片的浏览,如果考 ...

  5. 老调重弹:JDBC系列之<驱动加载原理全面解析) ----转

      最近在研究Mybatis框架,由于该框架基于JDBC,想要很好地理解和学习Mybatis,必须要对JDBC有较深入的了解.所以便把JDBC 这个东东翻出来,好好总结一番,作为自己的笔记,也是给读者 ...

  6. js与AMD模块加载

    目的: 了解AMD规范与CMD规范,写一个模块加载器雏形. 基本概念: AMD是异步模块定义规范,而CMD是通用模块定义规范.其他的还有CommonJS Modules规范. 对于具体的规范,可以参考 ...

  7. 【转】JS判断SWF,JPG加载完毕、兼容(Activex,plugIn)所有浏览器

    JS判断SWF,JPG加载完毕.兼容(Activex,plugIn)所有浏览器 这里主要说下监听SWF的加载. 网上流传已久的监听方法,只能在IE(Activex插件下)下实现.在使用plugin的浏 ...

  8. sea.js及三种加载方式的异同

      一.前言     浏览器本身并不提供模块管理的机制,过去网页开发中,为了使用各种模块,不得不在加入一大堆script标签.这样就使得网页体积臃肿,难以维护,还产生大量的HTTP请求,拖慢显示速度, ...

  9. RX系列四 | RxAndroid | 加载图片 | 提交表单

    RX系列四 | RxAndroid | 加载图片 | 提交表单 说实话,学RxJava就是为了我们在Android中运用的更加顺手一点,也就是RxAndroid,我们还是先一步步来,学会怎么去用的比较 ...

随机推荐

  1. intellij idea 常用快捷键让你事半功倍

    为什么谈这个 工欲善其事必先利其器,键盘流是必须的,快捷键首当其冲,请收下!!! 常用快捷键列表 Live Templates 自定义代码模板 取消屏幕的翻转,可以使用ctrl+alt+左右,进行代码 ...

  2. vue路由跳转时判断用户是否登录功能

    通过判断该用户是否登录过,如果没有登录则跳转到login登录路由,如果登录则正常跳转. 一丶首先在用户登录前后分别给出一个状态来标识此用户是否登录(建议用vuex): 简单用vuex表示一下,不会可以 ...

  3. java Static的使用

    static是一个静态修饰符,用于修饰成员(成员变量,成员函数).<thinking in java>对staic的使用场景有下面2种定义:“一种情形是只想用一个存储区域来保存一个特定的数 ...

  4. background背景透明内容不透明

    .demo{ padding: 25px; background-color:#000000;/* IE6和部分IE7内核的浏览器(如QQ浏览器)下颜色被覆盖 */ background-color: ...

  5. [luogu P3384] 【模板】树链剖分 [树链剖分]

    题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式 ...

  6. 导入 theano 失败。“cannot import name gof”

    按照网上教程安装好了 theano 之后,import theano 出现错误."cannot import name gof".网上找了很多教程,都不可行.最后找到如下教程.亲测 ...

  7. SetConsoleScreenBufferSize 函数--设置控制台屏幕缓冲区大小

    SetConsoleScreenBufferSize函数 来源:https://msdn.microsoft.com/en-us/library/windows/desktop/ms686044(v= ...

  8. 极简的Android RecyclerView Adapter(使用DataBinding)

    阅读本篇文章需要读者对Android Databinding和RecyclerView有一定的了解. 简介 我们知道,DataBinding的核心理念是数据驱动.数据驱动驱动的目标就是View,使用D ...

  9. 认识sass和webstrom的sass配置

    认识sass和webstrom的sass配置 我纳闷啊!电脑死机,我刚才编写的内容全没了. 呵呵! 一.sass的使用 1.首先要到官网下载个稳定的ruby版本,因为sass运行是需要ruby环境 它 ...

  10. [补档]暑假集训D8总结

    %dalao 今天有两位大佬来讲课,meaty来讲了Catalan(本来说好的莫比乌斯反演呢),聪聪来讲Splay呢 至于听课笔记= =,没来得及记= = 不过好不想上树啊,上了树就下不来了 考试 仍 ...