先后端分离以前端项目构建(grunt+require+angular)

前言

前段时间作了一个项目,前端开发页面,而后把代码给到后端同窗,后端同窗经过vm再来渲染页面。后来才发现,这种方式简直是太low了,由于前端代码在服务端同窗那里,每次前端须要更改的时候都须要去到服务端同窗那里修改代码,维护成本高,卖力不讨好==html

工做了这么久,深深的感觉到了那句名言的魅力,时间就是金钱呀!后来我发现,如今的web开发,谁还用这种低级的方法,你们都已经开始搞先后端分离了前端

先后端分离的目的和做用

要弄清先后端分离的目的和做用,首先要知道什么是先后端分离。node

如今的web前端愈来愈偏向于独立的技术种类,在不久的未来,服务端的活都会被咱们给承包了。我曾经在某个网站读到这样一句话,假若有一个大型网站,例如淘宝网,它确定不止是一个web项目,而是多个web项目的集合,那么若是前端不做整合、封装,那么不一样的项目开发必然会有大量的重复劳动。从这句话和我在前言中举的例子中能够看出,前端开发单独封装组件,单独开发项目,单独维护,前端代码不和服务端逻辑揉在一块儿,这就是我理解的先后端分离。惟一须要和服务端交互的,就是经过ajax去请求他们提供的接口。python

因此,从另外一个角度看,咱们在开发的时候,只要和服务端约定好接口格式,从项目开工到结束,咱们都不须要和服务端开发打交道,这无疑提升了项目质量和开发效率。先后端分离的终极目标应该是前端和服务端是彻底独立的项目,一个项目开始以后,前端开发前端的,服务端开发服务端的,而且最后还须要独立部署,这样才真正实现了先后端解耦分离,先后端的沟通主要集中在数据接口的格式上。jquery

前端项目构建

如今要作到前端项目独立,这时候为了项目便于管理维护,咱们就须要项目化,工程化,开发规范,自动化压缩混淆,自动化发布,前端优化等等。git

如今前端框架这么丰富,一个项目要引入哪些框架,就因人而异了,工做以来一直在学习angular,因此最近本身尝试着搭了一套基于grunt+requireJs+angularJs的应用。angularjs

  • grunt: 操做项目文件:好比文件转换、压缩、打包部署等等。github

  • requireJs: js库加载管理,支持按需加载,模块化引入。web

  • angularJs: js前端MVC框架,支持依赖注入、双向绑定等主要特性。ajax

这几个库是如今中大型前端项目比较适合的搭配,颇有必要去学习并掌握他们。

建立项目目录

mkdir myProject 
cd myProject

建立项目文件夹,而后进入文件夹,一下操做均在此文件夹下执行。

建立package.json

首先咱们须要为npm提供一个package.json,告诉它咱们的项目信息,特别是项目中将会使用的插件。

能够用命令生成,后续也可以手动修改。

npm init

他会问咱们一些问题,一路使用默认值,建立完毕。

安装grunt

npm install grunt --save-dev

使用npm安装grunt插件,它将被安装到根目录的node_modules文件夹下,全部npm插件都会放到这里。

--save-dev: 意思是安装插件的同时,也把它添加到项目信息文件package.json中的devDependencies字段里,意思是这个项目依赖于这些插件。下次使用npm install的时候就会自动安装这些插件。

为grunt建立配置文件Gruntfile.js

Gruntfile.js文件用于定义任务、任务组。它能够用来执行文件的类型转换、压缩、合并等等操做,为开发大大提升了效率。

  • 安装grunt-init

    npm install grunt-init -g      //全局安装grunt-init
  • 下载grunt模板

    git clone https://github.com/gruntjs/grunt-init-gruntfile.git ~/.grunt-init/gruntfile
  • 生成Gruntfile

    grunt-init gruntfile

    在项目根目录下生成Gruntfile.js文件,跟package.json文件一下,按需回答一些文件,就建立好了,后续能手动修改(其实大部分都是本身手写的)。

安装bower

bower是用来管理js库的一个工具,好比下载jquery、angularjs等库。而且下载的时候还能指定库的版本。

一样适用npm进行安装。

npm install bower -g

为bower生成配置文件bower.json

整个项目的信息文件是package.json,执行任务插件grunt的信息文件是Gruntfile.js,那么bower固然也有本身的信息文件了,那就是bower.json

bower init

不过我以为bower.json基本没有什么做用,它最大的做用就是用来下载咱们须要的各类技术库。

好比使用bower下载angularjs:

bower install angularjs

这行命令将会把angular下载下来,放在根目录下的bower_components文件夹下,不过它默认下载的是angular的最新版,有时候,咱们可能不须要最新版。假如,我想下载angularjs 1.2.2版本该怎么办呢?

bower install angularjs#1.2.2

另外,bower只负责下载文件到bower_components目录下,可是咱们项目中可能并不想把库放在这里,因此咱们能够选择使用grunt的插件grunt-bower-task,在Gruntfile.js中定义一个任务来移动文件到想要的目录下。

关于Requirejs

官网上是这样说的:

RequireJS的目标是鼓励代码的模块化。

它使用了不一样于传统的脚本加载步骤。能够用它来加速、优化代码,但其主要目的仍是为了代码的模块化,按需加载。

使用Requirejs

<script data-main="scripts/main" src="scripts/require.js"></script>

通常在首页加载requiejs文件,而后属性data-main指定的文件就是接下来要加载的文件,而后咱们再看main.js文件:

require.config({
    baseUrl: 'script/lib',
    paths: {
        app: 'app',
        jquery: '/jquery/jquery-min',
        angular: '/angularjs/angular-min'
    },
    shim: {
        'angular': {
            exports: 'angular'
        }
    }
});
require([
    'app'
], function(app) (
    app.hello();
))
  • 咱们在paths中声明了3个模块,app、jquery和angular,后面的路径是模块对应的文件路径。

  • shim中用来处理一些没有遵照requirejs规范的js库,好比angularjs库,因此要手动配置一个叫angular的模块。

  • 最后用require来导入咱们本身的模块,可在后面的callback中拿到对应模块的实例,并对它进行一些操做,好比咱们调用了app.hello()方法。

AngularJs实例

上面的步骤只是简单说了下大致步骤,纸上谈兵以后,就能够开始实际操做了。

目录结构

项目文件夹结构以下图(固然目录结构因人而异):

  • node_modules: 用来存放项目依赖的grunt插件。

  • bower_components: 用来存放bower下载的库。

  • build: 用来存放通过build处理以后的js文件。

  • app: 是真正的开发须要的文件。

    • data: 用来存放mock数据用的json文件。

    • images: 用来存放静态图片。

    • scripts: 用来存放全部js文件。

      • controller: 用来存放控制器文件。

      • directive: 定义的指令文件。

      • filter: 定义的过滤器文件。

      • route: 路由文件。

      • service: 服务文件。

      • vendor: 公共库文件,好比angular,jquery,bootstrap等等。

    • styles目录用来存放样式文件。

    • views目录用来存放页面html文件。

    • partials目录用来存放页面片断的html文件。

目录建立好了,如今来写一些代码,让项目可以运行起来。

views/index.html

<html>
<head>
    <meta charset="UTF-8">
    <title>grunt+requirejs+angular项目构建</title>
    <script src="../scripts/vendor/requirejs/require.js" data-main="../scripts/config"></script>    <!-- 先引入requirejs, 而后引入config.js -->
</head>
<body>
    <div ng-controller="testController">
        {{app}}
    </div>
</body>
</html>

上述index中,先引入了require.js,而后加载data-main对应的config.js文件。

scripts/config.js

var vendorPath = 'vendor/';
require.config({    //配置模块
    baseUrl: '../scripts/',
    paths: {
        'app': 'app',
        'angular': vendorPath + 'angular/angular',
        'jquery': vendorPath + 'jquery/jquery'
    },
    shim: {   //处理没有遵照requirejs规范的js库
        'angular': {
            exports: 'angular'
        }
    }
});
require(['./bootstrap'], function(bootstrap) {
    // ...
});

而后经过require引入了bootstrap.js文件。

scripts/bootstrap.js

define([
    'angular',
    'app',
    'jquery',
    './controller/_base'
], function(angular) {
    // 手动将angular模块绑定到document对象
    angular.element(document).ready(function() {
        angular.bootstrap(document, ['myProject']);
    });
});

注意:function的内容是requirejs引入全部文件以后的回调函数。

bootstrap是angular对象的一个方法,用于手动启动。上述代码除了引入了angular等js库外,还引入了app.js文件。

scripts/app.js

define([
    'angular',
    './controller/controllers'
], function(angular) {
    //定义将要绑定到document上的模块名称
    return angular.module('myProject', ['projectController']);
});

定义模块名myProject的时候,同时指定它依赖于另外一个模块projectController

同时在./controller/controllers.js中定义这个模块:

define(['angular'], function(angular) {
    return angular.module('projectController', []);
});

这里是给全部的控制器定义了一个单独的模块,而后让主要模块依赖于这个模块,这样作的目的是方便管理维护,咱们还能够给全部的服务、路由、过滤器都添加一个单独的模块,而后在app.js中添加注入便可。

controller/testController.js

若是想要让视图文件views/index.html可以看到效果,咱们就要开始编写控制器文件了,

define([
    './controllers'
], function(mod) {
    var controllerFn = function($scope, $location) {
        $scope.app = 'hello, world';
    };
    controllerFn.$inject = ['$scope', '$location'];
    mod.controller('testController', controllerFn);
});

引入控制器的单独模块文件'./controllers',而后在模块上新建一个名为testController的控制器,并在$scope上绑定了一个值为‘hello, world’的变量app

查看效果

使用python -m SimpleHTTPServer启动一个简单的web服务器,默认监听8000端口。在浏览器输入正确地址就能看到效果了。

hello, world

结语

如今,咱们须要作的就是,和服务端约定好接口格式,本身根据格式mock须要的数据,而后,咱们能够为所欲为的开发咱们的项目了,不用再和人打交道了。开发完毕以后,再经过grunt压缩、合并、打包文件等操做,暴露给外部的只需一个js文件,另外还能够经过git等版本管理工具来迭代项目。有了这种开发方式,你不再用担忧服务端开发随时来烦你,本身也有更多时间来钻研前端自己的技术了,哈哈。

相关文章
相关标签/搜索