zoukankan      html  css  js  c++  java
  • 前后端分离之前端项目构建(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等版本管理工具来迭代项目。有了这种开发方式,你再也不用担心服务端开发随时来烦你,自己也有更多时间来钻研前端本身的技术了,哈哈。

  • 相关阅读:
    multidownloadXkcd 多线程抓图
    51job_selenium测试2
    51job_selenium测试
    python爬虫 前程无忧网页抓取
    化工pdf下载
    Velocity写法注意
    Velocity中文乱码问题解决方法
    velcoity使用说明:foreach指令
    strults2标签s:set的用法
    struts提交action乱码
  • 原文地址:https://www.cnblogs.com/jarson-7426/p/5452638.html
Copyright © 2011-2022 走看看