使用 Twitter Bootstrap 的 Browserify

37

在stackoverflow上有许多类似的问题,包括答案,但它们都没有对我起作用,所以我来问你们了。感谢大家的时间。

我最近开始使用gulp和browserify,效果非常好。然后我尝试使用browserify为前端使用Backbone和Bootstrap3。

似乎所有东西都正常工作,直到我尝试require Bootstrap附带的js文件时,我在Chrome开发者工具中收到错误消息:jQuery未定义。

我已经尝试过用shim解决,但是我很困惑shim的具体操作。我使用的是jQuery 2.1.1版本,所以我不需要shim jQuery,但是由于我绝望地试图尝试所有方法,它仍存在于shim中。以下是我的package.json和main.js文件:

--------------package.json------------------

{
  "name": "gulp-backbone",
  "version": "0.0.0",
  "description": "Gulp Backbone Bootstrap",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Rob Luton",
  "license": "ISC",


  "devDependencies": {
    "jquery": "^2.1.1",
    "backbone": "^1.1.2",
    "browserify": "^4.2.1",
    "gulp": "^3.8.6",
    "vinyl-source-stream": "^0.1.1",
    "gulp-sass": "^0.7.2",
    "gulp-connect": "^2.0.6",
    "bootstrap-sass": "^3.2.0",
    "browserify-shim": "^3.6.0"
  },

  "browser": {
    "bootstrap": "./node_modules/bootstrap-sass/assets/javascripts/bootstrap.js",
    "jQuery": "./node_modules/jquery/dist/jquery.min.js"
  },

  "browserify": {
    "transform": ["browserify-shim"]
  },

  "browserify-shim": {
    "jquery": "global:jQuery", 
    "bootstrap": {
      "depends": [
        "jQuery"
      ]
    }
  }
}

------------------------- main.js ----------------------

var shim = require('browserify-shim');
$ = require('jquery');
var Backbone = require('backbone');
Backbone.$ = $;
var bootstrap = require('bootstrap');

/* the following logs fine if I comment out the bootstrap require, otherwise I get 'jQuery undefined' */

console.log(Backbone);
$(function() {
    alert('jquery works');
});

你可能会对Bootstrap UMD脚手架感兴趣,该脚手架已在https://github.com/twbs/bootstrap/pull/13904中被移除。 - cvrebert
如果您不想使用browserify-shim,请查看我的回答https://dev59.com/p18f5IYBdhLWcg3wJf0H#24981030 - Ian Lim
4个回答

52

如果你已经通过npm安装了jquery,那么就不需要这样进行shim。以下是我编写的项目可行的方法:

我也发现使用npm安装bootstrap有点麻烦。当需要进行此类shim时,我一直在使用bower来安装和维护特定的前端组件。

package.json:

{
  "name": "...",
  "version": "0.0.1",
  "description": "...",
  "repository": {
    "type": "git",
    "url": "..."
  },
  "browser": {
    "d3js": "./bower_components/d3/d3.min.js",
    "select2": "./bower_components/select2/select2.min.js",
    "nvd3js": "./bower_components/nvd3/nv.d3.min.js",
    "bootstrap": "./node_modules/bootstrap/dist/js/bootstrap.js"
  },
  "browserify": {
    "transform": [
      "browserify-shim",
      "hbsfy"
    ]
  },
  "browserify-shim": {
    "d3js": {
      "exports": "d3",
      "depends": [
        "jquery:$"
      ]
    },
    "bootstrap": {
      "depends": [
        "jquery:jQuery"
      ]
    },
    "select2": {
      "exports": null,
      "depends": [
        "jquery:$"
      ]
    },
    "nvd3js": {
      "exports": "nv",
      "depends": [
        "jquery:$",
        "d3js:d3"
      ]
    }
  },
  "devDependencies": {
    "browserify-shim": "~3.4.1",
    "browserify": "~3.36.0",
    "coffeeify": "~0.6.0",
    "connect": "~2.14.3",
    "gulp-changed": "~0.3.0",
    "gulp-imagemin": "~0.1.5",
    "gulp-notify": "~1.2.4",
    "gulp-open": "~0.2.8",
    "gulp": "~3.6.0",
    "hbsfy": "~1.3.2",
    "vinyl-source-stream": "~0.1.1",
    "gulp-less": "~1.2.3",
    "bower": "~1.3.3",
    "cssify": "~0.5.1",
    "gulp-awspublish": "0.0.16",
    "gulp-util": "~2.2.14",
    "gulp-rename": "~1.2.0",
    "gulp-s3": "git+ssh://git@github.com/nkostelnik/gulp-s3.git",
    "gulp-clean": "~0.2.4",
    "process": "~0.7.0"
  },
  "dependencies": {
    "backbone": "~1.1.2",
    "jquery": "~2.1.0",
    "lodash": "~2.4.1",
    "d3": "~3.4.8",
    "rickshaw": "~1.4.6",
    "datejs": "~1.0.0-beta",
    "moment": "~2.7.0"
  }
}

js:

$ = jQuery = require('jquery');
var _ = require('lodash');
var Rickshaw = require('rickshaw');
var d3 = require('d3js');
var nvd3 = require('nvd3js');
var moment = require('moment');
require('datejs');
require('select2');

var bootstrap = require('bootstrap');
console.log(bootstrap)

另外,有时候一个有用的方法是让browserify-shim输出其诊断信息。这是我的browserify.js任务的样子:

var browserify   = require('browserify');
var gulp         = require('gulp');
var handleErrors = require('../util/handleErrors');
var source       = require('vinyl-source-stream');
var process      = require('process');

process.env.BROWSERIFYSHIM_DIAGNOSTICS=1;

var hbsfy = require('hbsfy').configure({
  extensions: ['html']
});

gulp.task('browserify', ['images', 'less'], function(){
    return browserify({
      transform: ['hbsfy', 'cssify'],
            entries: ['./src/javascript/app.js'],
        })
        .bundle({debug: true})
        .on('error', handleErrors)
        .pipe(source('app.js'))
        .pipe(gulp.dest('./build/'));
});

1
非常感谢您的回复。问题集中在Twitter Bootstrap上,这是导致头痛的原因。正如我所提到的,我明白我不应该需要Shim jQuery,我只是尝试着想到的一切来让Bootstrap.js与Browserify配合使用,而它依赖于jQuery。jQuery在我的示例中实际上运行得很好,但当我使用require 'bootstrap'这一行时,控制台会显示“jQuery未定义”错误。所以我可能没有正确地对Bootstrap进行Shim。希望这样清楚了。再次感谢您的回复。 - rob.luton
谢谢!我还没有机会尝试,但这个例子恰好代表了我需要的东西。 - rob.luton
很酷,它在我的电脑上编译通过了,希望它对你也能正常工作。 - urban_raccoons
谢谢。我解决了我的bootstrap问题。正如评论中提到的,使用jquery:jQuery而不是jquery:$就可以了。 - Dmitri Pavlutin
@vamsiampolu 感谢您指出这一点。由于某种原因,我的设置可以使用 $ 或 jQuery 进行构建,但是查看 bootstrap 代码后,我同意应该使用 jQuery,所以我已经更改了答案。很抱歉让您等了这么久才更新答案! - urban_raccoons
显示剩余2条评论

26

在使用browserify时,出现了一个错误,要求定义变量'$'或'jQuery'。

将window添加以使其全局可用可以解决这个错误。如果这不是正确的做法,请告诉我。

window.$ = window.jQuery = require('jquery');
var bootstrapjs = require('bootstrap-sass');

只有在使用jquery npm依赖项而不是bower时,这才是完美的答案!无需添加shim :) - HADI
它能用,但感觉有点像临时抱佛脚... Browserify 的目的不是避免这种情况吗? - art-solopov
1
@art-solopov 这种方法有些取巧,但要么这样做,要么重新编写第三方库以使其支持 CommonJS。 - Phil Cooper
这一行代码的修改解决了我的问题。 - Salkz

1

如果要让BootstrapBrowserify一起工作,您需要其中之一 Browserify CSS transforms

首先是index.js(browserify入口)

// Bootstrap needs jQuery on the Window
window.jQuery = $  = require('jquery');
// include popper.js if you want Bootstrap tooltips
window.Popper = require('popper.js');
// include bootstrap js libs (not the CSS libs as yet)
require('bootstrap');
// then the CSS Lib
require('bootstrap/dist/css/bootstrap.css');

NPM Installs: (英文原文的意思为:NPM安装)
npm install bootstrap@4.0.0-alpha.6 jquery popper.js

全局使用工具提示:

根据 Bootstrap 文档

$('[data-toggle="popover"]').popover();

我有一个 Browserify-Budo 存储库在这里。如果你想看它的工作原理。


1

我一直对此有疑问。这个简单的解决方案对我非常有效:

import foo from 'foo';
import bar from './bar';
import { default as $ } from "jquery";
global.$ = $;
global.jQuery = $; // This one does the trick for bootstrap!
// Boostrap's jQuery dependency only works with require, not with ES6 import!
const btp = require('bootstrap');

1
现在,如何以类似的方式包含Bootstrap CSS依赖项,而不是直接将其添加到HTML文件中? - jollege

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接