前后端分離之前端項目構建(grunt+require+angular)


前言

前段時間做了一個項目,前端開發頁面,然后把代碼給到后端同學,后端同學通過vm再來渲染頁面。后來才發現,這種方式簡直是太low了,因為前端代碼在服務端同學那里,每次前端需要更改的時候都需要去到服務端同學那里修改代碼,維護成本高,賣力不討好==

工作了這么久,深深的感受到了那句名言的魅力,時間就是金錢呀!后來我發現,現在的web開發,誰還用這種低級的方法,大家都已經開始搞前后端分離了

前后端分離的目的和作用

要弄清前后端分離的目的和作用,首先要知道什么是前后端分離。

現在的web前端越來越偏向於獨立的技術種類,在不久的將來,服務端的活都會被我們給承包了。我曾經在某個網站讀到這樣一句話,假如有一個大型網站,例如淘寶網,它肯定不止是一個web項目,而是多個web項目的集合,那么如果前端不作整合、封裝,那么不同的項目開發必然會有大量的重復勞動。從這句話和我在前言中舉的例子中可以看出,前端開發單獨封裝組件,單獨開發項目,單獨維護,前端代碼不和服務端邏輯揉在一起,這就是我理解的前后端分離。唯一需要和服務端交互的,就是通過ajax去請求他們提供的接口。

所以,從另一個角度看,我們在開發的時候,只要和服務端約定好接口格式,從項目開工到結束,我們都不需要和服務端開發打交道,這無疑提高了項目質量和開發效率。前后端分離的終極目標應該是前端和服務端是完全獨立的項目,一個項目開始之后,前端開發前端的,服務端開發服務端的,並且最后還需要獨立部署,這樣才真正實現了前后端解耦分離,前后端的溝通主要集中在數據接口的格式上。

前端項目構建

現在要做到前端項目獨立,這時候為了項目便於管理維護,我們就需要項目化,工程化,開發規范,自動化壓縮混淆,自動化發布,前端優化等等。

現在前端框架這么豐富,一個項目要引入哪些框架,就因人而異了,工作以來一直在學習angular,所以最近自己嘗試着搭了一套基於grunt+requireJs+angularJs的應用。

  • grunt: 操作項目文件:比如文件轉換、壓縮、打包部署等等。

  • requireJs: js庫加載管理,支持按需加載,模塊化引入。

  • angularJs: js前端MVC框架,支持依賴注入、雙向綁定等主要特性。

這幾個庫是現在中大型前端項目比較適合的搭配,很有必要去學習並掌握他們。

創建項目目錄

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM