bootstrap源码分析系列:一,文件结构和开发环境

来源:互联网 发布:手机网络制式 编辑:程序博客网 时间:2024/06/06 02:20
本文基于bootstrap2.3.2。

一,文件结构:

▾ docs/
  ▸ assets/
  ▸ build/
  ▸ examples/
  ▸ templates/
    base-css.html
    components.html
    customize.html
    extend.html
    getting-started.html
    index.html
    javascript.html
    scaffolding.html
▸ img/
▸ js/
▸ less/
▸ node_modules/
  bower.json
  CHANGELOG.md
  composer.json
  CONTRIBUTING.md
  LICENSE
  Makefile
  package.json
  README.md

文件结构如上所示,其中:
docs:文档,里面其实有两种文档,docs根目录下的是有templates里面的模板编译生成的,examples里面是直接写的html没有用模板。assets目录里面好包括了从根目录copy过去的bootstrap代码(js,css和img)。其中templates下的模板是用mustache写的,mustache是一个通用的无逻辑模板语言,http://mustache.github.io/, 其中js的实现是hogan。
img: 两种sprite icon
js:js源码,这里没有用任何工具解决依赖,是通过在make的时候指定文件顺序来解决模块依赖关系的。
less:less源码,这里有两个入口文件分别是bootstrap和responsive。
bootstrap可以按顺序分成如下几个部分:
1,变量和函数:variables.less,mixins.less
2,重置默认样式:reset.less
3,脚手架:scaffolding.less,grid.less,layout.less
4,基础样式:type.less,form.less,tables.less
5,css组件:btn nav等
6,js组件:popover, dialog

Makefile:make脚本,下面会详细讲

在执行make之后会生成bootstrap目录,里面就是编译后的js和css文件。
2.3和3.0在文件结构上也有些区别:
1,用icon font代替了img
2,用grunt代替了make

二,代码构建工具makefile:

bootstrap使用make脚本构建代码,但是make脚本实际上是调用nodejs,所以仍然需要执行npm install之后才能执行make。
make实际上定义了四种任务:
1,编译源码,包括js和css,输出到bootstrap目录下
2,测试,包括了hint进行语法检查和qunit进行单元测试
3,构建文件,这里包括两个步骤,一是调用npm插件编译mustache模板,二是把必要的文件从根目录拷贝到docs/assets目录下
4,watch

在3.0版本中,make已经被grunt取代了,如果使用2.3但是任然想使用grunt而不是make,可以参考3.0版本的grunt脚本进行修改。等价的Gruntfile.js如下:

/* jshint node: true */exec = require("child_process").exec;module.exports = function(grunt) {  'use strict';  grunt.initConfig({    pkg: grunt.file.readJSON('package.json'),    banner: '/*dpl started*/',    distRoot: 'dist',    docsRoot: 'docs',    clean: {      dist: ['<%= distRoot %>']    },    jshint: {      options: {        jshintrc: 'js/.jshintrc'      },      gruntfile: {        src: 'Gruntfile.js'      },      src: {        src: ['js/*.js']      },      test: {        src: ['js/tests/unit/*.js']      }    },    concat: {      options: {        banner: '<%= banner %>',        stripBanners: false      },      bootstrap: {        src: [          'js/bootstrap-transition.js',          'js/bootstrap-alert.js',          'js/bootstrap-button.js',          'js/bootstrap-carousel.js',          'js/bootstrap-collapse.js',          'js/bootstrap-dropdown.js',          'js/bootstrap-modal.js',          'js/bootstrap-tooltip.js',          'js/bootstrap-popover.js',          'js/bootstrap-scrollspy.js',          'js/bootstrap-tab.js',          'js/bootstrap-affix.js'        ],        dest: '<%= distRoot %>/js/<%= pkg.name %>.js'      },    },    uglify: {      options: {        banner: '<%= banner %>'      },      bootstrap: {        src: ['<%= concat.bootstrap.dest %>'],        dest: '<%= distRoot %>/js/<%= pkg.name %>.min.js'      }    },    recess: {      options: {        compile: true      },      bootstrap: {        src: ['less/bootstrap.less'],        dest: '<%= distRoot %>/css/<%= pkg.name %>.css'      },      reponsive: {        src: ['less/responsive.less'],        dest: '<%= distRoot %>/css/<%= pkg.name %>-responsive.css'      },      min: {        options: {          compress: true        },        src: ['less/bootstrap.less'],        dest: '<%= distRoot %>/css/<%= pkg.name %>.min.css'      },      minresponsive: {        options: {          compress: true        },        src: ['less/responsive.less'],        dest: '<%= distRoot %>/css/<%= pkg.name %>-responsive.min.css'      }    },    copy: {      docs: { //doc 必须依赖于bootstap.min.js        files: [          { expand: true, src: ['img/*'], dest: '<%= docsRoot %>/assets/' },          { expand: true, src: ['js/*.js'], dest: '<%= docsRoot %>/assets/' },          { expand: true, src: ['fonts/*'], dest: '<%= docsRoot %>/assets/' },          { expand: true, cwd: 'js/test/vendor/', src:['jquery.js'], dest: '<%= docsRoot %>/assets/js/' },          { expand: true, cwd: '<%= distRoot %>/js/', src: ['<%= pkg.name %>.js'], dest: '<%= docsRoot %>/assets/js/' },          { expand: true, cwd: '<%= distRoot %>/css/', src: ['<%= pkg.name %>.css'], dest: '<%= docsRoot %>/assets/css/' }        ]      }    },    qunit: {      options: {        inject: 'js/tests/unit/bootstrap-phantom.js'      },      files: ['js/tests/*.html']    },    connect: {      server: {        options: {          port: 3000,          base: '.'        }      }    },    watch: {      css: {        files: 'less/*.less',        tasks: ['recess']      },      js: {        files: 'js/*.js',        tasks: ['dist-js']      }    }  });  // These plugins provide necessary tasks.  grunt.loadNpmTasks('grunt-contrib-clean');  grunt.loadNpmTasks('grunt-contrib-concat');  grunt.loadNpmTasks('grunt-contrib-connect');  grunt.loadNpmTasks('grunt-contrib-copy');  grunt.loadNpmTasks('grunt-contrib-jshint');  grunt.loadNpmTasks('grunt-contrib-qunit');  grunt.loadNpmTasks('grunt-contrib-uglify');  grunt.loadNpmTasks('grunt-contrib-watch');  grunt.loadNpmTasks('grunt-html-validation');  grunt.loadNpmTasks('grunt-jekyll');  grunt.loadNpmTasks('grunt-recess');  grunt.loadNpmTasks('browserstack-runner');  // Test task.  var testSubtasks = ['dist-css', 'jshint'];  grunt.registerTask('test', testSubtasks);  grunt.registerTask('hogan', 'compile mustache template', function() {    var done = this.async();    var child = exec('node docs/build', function(e) { done(); })  });  // JS distribution task.  grunt.registerTask('dist-js', ['concat', 'uglify']);  // CSS distribution task.  grunt.registerTask('dist-css', ['recess']);  // Full distribution task.  grunt.registerTask('dist', ['clean', 'dist-css', 'dist-js']);  grunt.registerTask('docs', ['dist', 'hogan', 'copy']);  // Default task.  grunt.registerTask('default', ['test', 'dist']);}


1 0