【问题标题】:Custom Bootstrap 3 pipeline by example [closed]通过示例自定义 Bootstrap 3 管道 [关闭]
【发布时间】:2015-10-22 12:16:07
【问题描述】:

我有兴趣使用自己的颜色和主题自定义 Twitter Bootstrap 3。我对使用网络工具或专有(付费)工具感兴趣,并希望通过创建一个需要一些初始设置的“管道”(从命令行运行)来实现这一点工件(LESS 文件等)并将它们转换为完全缩小的自定义 Bootstrap 版本。

我对基本流程的理解是:

我不明白的是:

  • 什么工具(LESS、grunt、bower 等)压缩了这条管道,我们将它们用于什么(具体)? LESS、grunt 和 bower 是否都做相同的事情,或者它们处理不同的转换/操作(如果是,是什么)?
  • TB3 CSS 和 JS 的初始工件是什么?它们是什么类型的文件?
  • 如何实现缩小/丑化?由于我们使用命令行工具来生成我的自定义 TB3,这些可以只是“任何”旧的 minifier/uglifier 吗?

【问题讨论】:

  • 嗯,从阅读getbootstrap.com/getting-started/#grunt开始。简而言之:grunt 只是您使用的所有工具的外壳/环境(包括更少的编译器、压缩器等)。显然,您可以使用任何其他环境(例如gulp)来实现相同的目的。 “它们是什么类型的文件?” - 更少(或 SCSS)和 JS。
  • 这里有一些额外的资源Creating a Custom Bootstrap Build | Starter kit to use Gulp with Less. | gulpjs 因为有多种方法可以使用许多不同的工具来做到这一点。您最好找到一些教程,因为 YouTube 上有数不胜数的资源。
  • 您还可以考虑创建一个自定义 Yeoman 生成器,其中包括您需要的所有工具、Grunt/Gulp、SASS、LESS 等。所有这些都从命令行运行。
  • 感谢@PetrusRex (+1) 的建议-如果您可以在答案形式中进行解释,则可以回答我的问题并解释它们与“Yeoman”的关系,我很乐意给你(或其他任何想要这样做的人!)绿色支票和赏金!

标签: css twitter-bootstrap gruntjs less bower


【解决方案1】:

我认为流水线的想法是有效的,并不过分,因为它加快了开发周期。我有一个项目可以作为起点。

https://github.com/mhanney/twitter-bootstrap-customization

它按照您的建议使用 Grunt、Bower 和 LESS,并且还优化了 css 和 js。我称它为管道,因为它使用grunt-contrib-watchgrunt-contrib-connect 在文件更改时重建和重新加载文件。与使用 point and click web UI 相比,这使得迭代主题所需的时间要少得多。

我以这种方式进行自定义构建的动机不仅是为了自定义主题,而且是为移动 Web 应用程序制作更小的 Bootstrap.css 和 Bootstrap.js。很多类和js函数可以省略。我使用uncssprocesshtml grunt 插件的组合来做到这一点。

我上面链接的项目是我的典型移动网络应用程序构建过程的简化版本。 gruntfile.js 中的 cmets 应该有助于阐明管道中每个步骤的作用。我在这里的答案中包含了 package.json、bower.json、gruntfile.js 和 README 以供快速参考,但您也需要其他部分。

@staypuftman 和@Hitmands 很重要。为什么对@Hitmands 投反对票?这是一个很好的答案。总是有不止一种方法可以做到这一点。

package.json

{
  "name": "Twitter-Bootstrap-Customization-Pipeline-Example",
  "description": "Twitter Bootstrap Customization Pipeline using Grunt",
  "version": "0.0.1",
  "build": "1",
  "license": "MIT",
  "repository": "git@github.com:mhanney/twitter-bootstrap-customization.git",
  "private": false,
  "author": {
    "name": "mhanney",
    "url": "https://github.com/mhanney/twitter-bootstrap-customization"
  },
  "devDependencies": {
    "bower": "^1.4.1",
    "connect": "~3.4.0",
    "grunt": "^0.4.5",
    "grunt-autoprefixer": "^3.0.3",
    "grunt-bower-task": "^0.4.0",
    "grunt-cli": "0.1.13",
    "grunt-contrib-clean": "^0.6.0",
    "grunt-contrib-concat": "^0.5.1",
    "grunt-contrib-connect": "^0.10.1",
    "grunt-contrib-cssmin": "~0.12.3",
    "grunt-contrib-less": "^1.0.1",
    "grunt-contrib-uglify": "^0.10.0",
    "grunt-contrib-watch": "0.6.1",
    "grunt-processhtml": "~0.3.8",
    "grunt-uncss": "~0.4.3",
    "less-plugin-autoprefix": "^1.4.2"
  }
}

bower.json

{
  "name": "Twitter-Bootstrap-Customization-Pipeline-Example",
  "version": "0.0.1",
  "dependencies": {
    "bootstrap": "~3.3.5"
  },
  "private": false
}

gruntfile.js

module.exports = function(grunt) {

  'use strict';

  grunt.loadNpmTasks('grunt-bower-task');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-uncss');
  grunt.loadNpmTasks('grunt-processhtml');
  grunt.loadNpmTasks('grunt-contrib-cssmin');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-clean');

  grunt.initConfig({

    // variable to the location of the bootstrap javascript source
    dirs: {
      'bootstrapjs': 'bower_components/bootstrap/js',
    },

    // defer to bower.json to decide which bower packages to install
    bower: {
      install: {}
    },

    // Process the bootstrap less files.
    // The paths setting here is critical.
    // We include all of the bootstrap less files from bower,
    // then incude our modifications and overrides to
    // bootstrap by bringing in the file src/theme/build.less.
    // Our build.less is actually a list of more includes.
    // This is a shortcut. We could have listed all our less includes
    // here instead.
    //
    // We then use the less-plugin-autoprefix plug-in to
    // only add brower specific prefixes for our known target audience -
    // in my case this is mobile browsers - iOS and Android.
    // The result of the less build is placed into our 'intermediate' directory
    // for the optimization steps.
    less: {
      default: {
        options: {
          paths: ['bower_components/bootstrap/less'],
          compress: false,
          strictMath: true,
          plugins: [
            new(require('less-plugin-autoprefix'))({
              browsers: ['iOS >= 7', 'Android >= 4', 'last 2 versions']
            })
          ],
        },
        files: {
          'intermediate/bootstrap-custom.css': 'src/theme/build.less'
        },
      }
    },

    // css minification
    cssmin: {
      minify: {
        expand: false,
        src: 'intermediate/bootstrap-custom.css',
        dest: 'public/bootstrap-custom.min.css'
      }
    },

    // uncss removes css styles not found in src/index.html
    uncss: {
      public: {
        files: {
          'public/bootstrap-custom.css': ['src/index.html']
        }
      }
    },

    // The file 'src/index.html' gets transformed by processhtml to use our
    // optimized 'uncss' version of bootstrap.
    // The processed index.html is copied into the `public`
    // directory where it is served by connect
    processhtml: {
      public: {
        files: {
          'public/index.html': ['src/index.html'],
        }
      }
    },
    // Declare which components of bootstrap.js to include.
    // Concatenate the files we choose into one file
    // called bootstrap-custom.js in the `intermediate`
    // directory where it will get processed by the next
    // step in the pipeline - `uglify` for js minification.
    // Be very careful here not to cut too munch of Bootstrap's
    // functionality. I do this optimization only when I am absolutely sure
    // that whole features - such as modals - are not used in a mobile
    // we app.
    concat: {
      bootstrap: {
        src: [
          '<%=dirs.bootstrapjs%>/transition.js',
          //'<%=dirs.bootstrapjs%>/alert.js',
          //'<%=dirs.bootstrapjs%>/button.js',
          //'<%=dirs.bootstrapjs%>/carousel.js',
          '<%=dirs.bootstrapjs%>/collapse.js',
          //'<%=dirs.bootstrapjs%>/dropdown.js',
          //'<%=dirs.bootstrapjs%>/modal.js',
          //'<%=dirs.bootstrapjs%>/tooltip.js',
          //'<%=dirs.bootstrapjs%>/popover.js',
          //'<%=dirs.bootstrapjs%>/scrollspy.js',
          //'<%=dirs.bootstrapjs%>/tab.js',
          //'<%=dirs.bootstrapjs%>/affix.js'
        ],
        dest: 'intermediate/bootstrap-custom.js'
      }
    },

    // js minification
    // A standard uglification task.
    // Takes the bootstrap js from the `intermediate`
    // dir and puts a minified copy in `public` - the dir
    // being served by node/connect for previewing.
    uglify: {
      options: {
        sourceMap: true
      },
      bootstrap: {
        files: {
          'public/bootstrap-custom.min.js': ['intermediate/bootstrap-custom.js']
        }
      }
    },

    // Start up a simple nodejs web server for fast reload of the test index
    // page that references our custom bootstrap css and js.
    // With livereload = true changes will update in the browser without having
    // to manually F5 reload in the browser.
    // We set keepalive to false, because the `watch` task has a
    // keepalive=true and that is enough to keep the
    // grunt task runner from stopping (which would stop connect)
    connect: {
      base: {
        options: {
          base: 'public',
          port: 8082,
          livereload: true,
          keepalive: false,
          open: true
        }
      }
    },

    // Run the css pipeline again if any of the following files change.
    // With livereload = true changes will update in the browser without having
    // to manually F5 reload in the browser.
    watch: {
      files: ['src/theme/bootstrap.less',
        'src/theme/variables.less',
        'src/theme/structural.less',
        'src/index.html'
      ],
      tasks: 'css',
      options: {
        livereload: true,
        nospawn: true
      }
    },

    // Utility task to clean up
    // the temporary `intermediate`
    // and `public` directories.
    // Be very, very careful running grunt clean:nuke
    // it only exists for making a really, really clean
    // source tree for pushing to source control.
    clean: {
      build: {
        src: ['intermediate/*.*',
      'public/*.*']
      },
      nuke: {
        src: ['bower_components',
        'lib',
        'node_modules',
        'intermediate',
        'public']
      }
    }
  });

  // We declare task `targets`, or aliases so that
  // we can call them individually on the command line
  // if we want. This is useful for testing the order in which
  // the tasks need to run. To run just one of these tasks,
  // do `grunt css` - for example.

  // declare a task target called 'css' that will do the
  // less, uncss, cssmin and processhtml tasks
  grunt.registerTask('css', ['clean:build', 'less', 'cssmin', 'processhtml:public']);

  // declare a task target called 'js' that will do the concat and uglify steps
  grunt.registerTask('js', ['concat', 'uglify']);

  // declare the default task that will run
  // the `css` target, followed by the `js` target.
  // Order is important here. We must build the css and js before
  // starting the `connect` local web server, and file watcher tasks
  grunt.registerTask('default', ['css', 'js', 'connect', 'watch']);

};

自述文件

Twitter Bootstrap 3 自定义管道示例

这是一个使用 grunt 自定义 Twitter Bootstrap 的构建过程。

动机

问题

  • Twitter Bootstrap 的流行使得所有使用它的网站看起来都差不多。 我们经常需要定制主题以与公司的品牌保持一致。 此外,Twitter Bootstrap CSS 对于移动浏览器来说实际上有点大(~130K) 并且通常包含许多未使用的样式。许多 JavaScript 组件 对于为移动 Web 应用程序量身定制的超精益构建,也可以删除。最后,网络点击工具很好,但在迭代设计时会耗费大量人力。我们需要一个持续的“观察和重建”管道。

解决方案

  • 使用 grunt 任务运行器,我们将构建一个高效的管道以 构建 Bootstrap JavaScript 和 CSS,优化输出,进行测试 index.html 页面,并让 grunt 监视源文件的更改,以便 管道自动重新开始,更改在浏览器中可见 无需按 F5 即可立即使用。

TL;DR

  • 安装节点和 npm

git clone git@github.com:mhanney/twitter-bootstrap-customization.git cd twitter-bootstrap-customization npm install --no-optional grunt bower grunt

什么做什么?

NPM

NPM 是 node 的包管理器。我们使用它来放置 grunt 任务(在 node_modules 中)。 我们只使用 NPM 来获取我们的构建管道工具。我们不使用 NPM 来获取我们的前端组件源。 尽管可以从 NPM 获取 Bootstrap 和 jQuery,但使用 Bower 更有意义, 因为 Bower 将前端资源放在 ~/lib 中——这是我们在 index.html 测试页面比 ~/node_modules 深处的资源。

凉亭

Bower 是前端 Web 组件的包管理器。 我们将使用它将引导源(及其依赖项 - jQuery)引入我们的项目。 就这些。我们仅使用 bower 将源文件(由其他方维护)复制到位。

bower grunt 任务下载 bootstrap 和 jQuery,并将它们的源代码放入 bower_components 并将它们的未压缩版本放入 lib。

如果 bower 任务失败并显示 - git ls-remote exit code of #128 - 那么您可能遇到阻止 git 协议的防火墙问题。解决方法是将协议更改为https:

git config --global url."https://".insteadOf git://

咕噜声

Grunt 是 JavaScript 的任务运行器。 我们将使用它来自动运行构建 Twitter Bootstrap 所涉及的命令。 Grunt 任务只是带有 JSON 中声明的参数的命令运行器。

grunt 任务是这样排序的:

  • Bootstrap LESS 文件转换为 CSS
  • CSS 为自定义浏览器列表添加了供应商特定的前缀
  • 通过检查使用 CSS 文件的页面删除未使用的 CSS 类
  • 处理 HTML 以包含优化的 CSS 而不是原来的
  • 优化后的 CSS 进一步缩小
  • 监视可编辑的 .less 文件并再次运行整个管道。
  • 浏览器会在检测到构建更改时自动刷新。
  • Twitter Bootstrap JavaScript 组件可以切换进出。
  • Twitter Bootstrap JavaScript 使用 uglify 缩小。

Less 是一个 CSS 预处理器,这意味着它扩展了 CSS 语言,添加了允许变量、mixin、函数和许多其他技术的功能,使您可以使 CSS 更易于维护、主题化和可扩展。

lesscss.org.

自定义

主题由三个 LESS 文件组成。 * src/theme/bootstrap.less - 要包含的其他文件列表 如果你知道有你绝对不使用的引导组件, 您可以在src/theme/bootstrap.less 中将它们注释掉 如果您破坏了某些内容,请不要担心,重新评论它是微不足道的。 * src/theme/variables.less,默认包含在 Bootstrap 中, 允许您自定义these settings。 * src/theme/structural.less 引入了更广泛的结构变化。

这些是唯一少被观看的文件。

优化

  • grunt-uncss 是一项用于从项目中删除未使用的 CSS 的繁重任务。这是针对移动网络的超级优化。在一些项目中,我通过删除未使用的样式将 ~130K Bootstrap.css 文件减少到不到 30K。

  • grunt-contrib-uglify 使用 Uglify 缩小 JavaScript

连接并自动重新加载

连接网络服务器进程将提供 public/index.html 文件 localhost:8082 并观察我们的文件是否有变化。

在检测到更改时,索引页面将自动在浏览器中重新加载。

版权和许可

版权所有 (c) 2014 "mhanney" Michael Hanney

特此免费授予任何人许可 获取此软件和相关文档的副本 文件(“软件”),在没有处理软件的情况下 限制,包括但不限于使用权, 复制、修改、合并、发布、分发、再许可和/或出售 软件的副本,并允许获得该软件的人 提供软件以执行此操作,但须遵守以下规定 条件:

以上版权声明及本许可声明为 包含在软件的所有副本或大部分内容中。

软件按“原样”提供,不提供任何形式的保证, 明示或暗示,包括但不限于保证 适销性、适合特定用途和 非侵权。在任何情况下,作者或版权均不得 持有人应对任何索赔、损害或其他责任负责, 无论是在合同、侵权或其他方面产生的 来自、脱离或与本软件或使用或 软件中的其他交易。

【讨论】:

  • 请否决我的答案的人可以发表评论解释原因吗?
  • 当然可以。这个问题应该以离题和过于宽泛的方式结束(而不是完全得到回答)。 Stackoverflow 不是博客/教程平台。并且 OP 应该学会使用 Google(“请给我一些 Grunt/Gulp/Less 教程”)。
  • @seven-phases-max 我明白了。我真的同意。
  • 哈哈@seven-phases-max。查看我的个人资料。近400个问题。方式,众包比阅读 900 页的技术手册要快得多,只要你想学习一些东西。每当我有一个棘手的问题时,我都会给它一个赏金,然后有人回答它。喜欢这里的 mhanney(+1,绿色支票和赏金 - 非常感谢!)
  • @smeeb 这被称为自私噪音。当然它对你有用(“请为我收集一些琐事以获得赏金”),但对其他人来说完全没用,并且直接与 SO 目的相矛盾(使其更难使用)。
【解决方案2】:

我跑了很多次这样的问题! 所以,相信我,请执行以下操作:

(使用咕噜声)

  1. 通过bower(或直接下载)将bootstrap-sources 放入源目录,通常是frontend/src(/scss 用于样式表和/ js for javascripts)
  2. 安装grunt-sass(使用libSass,比ruby编译器更快)
  3. 安装grunt-contrib-uglify
Consider using Sass instead of less because the next version of bootstrap drops less!

这就是为了拥有一个最小的构建系统! 当然,你可以从很多方面改进它,你可以从one that i made开始

希望有所帮助!

【讨论】:

    【解决方案3】:

    您的管道有点过头了。您只需要在 source 文件夹中设置项目(使用 Bootstrap + 其他依赖项和您的自定义主题代码),然后使用构建工具将所有内容一起编译到 destination 文件夹中。

    • GulpGrunt 是两个最常见的构建工具。 Grunt 配置比较重,Gulp 只使用 JS 脚本。两者都有大量的插件,您可以自定义以按照您想要的方式构建。他们实际上是使用您设置的命令从源文件构建您的网站。
    • Bower 是一个前端 JS 包管理器。它只是为您提供 JS 包,并将它们包含到您的项目中。
    • LESS 和大概是 Sass 是 CSS 预处理器,您可以在其中编写样式。您的构建工具将获取它们的内容并自动将它们转换为缩小的 CSS。

    如果这是您第一次从头开始制作这样的管道,请不要这样做。你会陷入困境。从另一个基地开始要容易得多。最好的选择之一是使用Yeoman,它构建了一个包含 Bower + Build Tools 的基本应用程序。

    我最喜欢的基础是他们的Gulp Webapp,其中包括 Bootstrap、Bower、Sass、Gulp,并且已经在gulpfile.js 中设置了构建管道(这将在项目的根目录中)。通读这个生成器的文档——它解释了你在这篇 SO 帖子中遇到的一堆问题。

    至于LESS 如何与构建管道一起工作:

    var less = require('gulp-less');
    var minifyCSS = require('gulp-minify-css');
    
    gulp.task('styles', function() {
        gulp.src(['app/styles/*.less'])
           .pipe(less())
           .pipe(minifyCSS())
           .pipe(gulp.dest('dist'))
           .pipe(refresh(server))
        })
    
    • 将所有自定义 LESS 样式文件(具有 .less 扩展名的文件)添加到 styles 子目录中,该子目录将位于上述 gulp-webapp 生成器的 app 文件夹中。这将是您的自定义样式代码。
    • 在您的构建中,您需要包含到gulp-less plugin 并如上所示实施。
    • 缩小是通过另一个名为 gulp-minify-css 的插件完成的,在上面的代码块中引用。

    【讨论】:

    • 感谢@staypuftman (+1)。几个后续问题:(1) 我可以假设 Bower 首先尝试从 CDN 加载 JS 文件吗?如果是这样,这些 CDN URL 是否可配置?另外,如果 CDN 确实返回任何内容,那么备份是什么? Bower 是否有自己的托管存储库? (2) 为简单起见,我们只使用由 LESS 组成的“管道”。您能否(重新)回答我最初的 3 个问题,仅使用 LESS 作为唯一工具?
    • 含义:(2a) LESS 实际会做什么(具体例子?),(2b) 我需要启动哪些具体工件with for LESS 和 (2c) 它如何与缩小一起工作?
    • 上面的错字更正^^^:而不是“...另外,如果CDN确实返回任何内容,备份是什么?”。应该是“另外,如果 CDN 没有返回任何东西,那么备份是什么?
    • 1- Bower 管理物理包,将它们放入项目中您引用的目录中。它不使用 CDN。但是,如果您希望在 prod 上的开发和 CDN 期间使用 Bower 的便利,您可以将 Gulp-CDNizer 添加到您的构建管道中:npmjs.com/package/gulp-cdnizer
    • 2- LESS 是一个 CSS 预处理器。这意味着您必须将样式编码为 LESS 使用的约定。它对构建没有影响。您的构建工具需要能够从 LESS > CSS 转换。 Gulp 和 LESS 如何通过这些插件之一进行交互(在本例中为 gulp-less:npmjs.com/package/gulp-less
    猜你喜欢
    • 2018-06-13
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 2021-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-09
    相关资源
    最近更新 更多