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

本文基于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
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值