先後端分離以前端項目構建(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等版本管理工具來迭代項目。有了這種開發方式,你不再用擔憂服務端開發隨時來煩你,本身也有更多時間來鑽研前端自己的技術了,哈哈。

相關文章
相關標籤/搜索