使用Browserify与Bootstrap 3.0

22

我正在尝试在Browserify 5.9.1 中使用 Bootstrap 3.0,但遇到以下错误:

Uncaught ReferenceError: jQuery is not defined

这应该怎样正确地完成?

这是我的package.json文件的相关部分:

{
  ...
  "scripts": {
    "bundle": "browserify main.js -o bundle.js --debug --list"
  },
  "dependencies": {
    "backbone": "~1.1.x",
    "jquery": "~2.1.x",
    "underscore": "~1.6.x"
  },
  "devDependencies": {
    "browserify": "^5.9.1",
    ...
  },
  ...
}

需要引入 Bootstrap 的模块如下:

var $ = require('jquery');
var Backbone = require('backbone');
Backbone.$ = $;
require('../../../../bower_components/bootstrap-sass-official/assets/javascripts/bootstrap');

我不喜欢这里的两件事:

  1. Bootstrap是使用Bower下载的。据我所知,没有办法使用npm获取它。这使得路径非常冗长和尴尬。是否有方法使Bootstrap更加适合npm?
  2. Bootstrap不是此模块的直接依赖项,它是一种jQuery插件。当它加载时,它仅在文档上创建一些事件处理程序来处理Bootstarp的小部件事件。我必须进行引用,以便创建这些事件处理程序。这样做正确吗?

当然,在所有这些之后,我仍然会收到“jQuery未定义”的错误。我正在绞尽脑汁尝试让它正常工作。请帮帮我!

P.S.早些时候,我在使用grunt-browserify插件,并很快意识到它使用了没有源映射功能的browserify 4.x版本。这使得调试变得更加困难,因此我迅速将其从图中删除,并直接从npm运行browserify。


Bootstrap没有被写成CommonJS模块。你需要自己添加样板代码。 - cvrebert
1
不管价值如何,Bootstrap现在可以通过NPM获取。这将有助于解决您对不友好的require路径的第一个关注点。 :) - Jonathan Mast
3个回答

33
这对我而言很有效,当我在使用browserify时使用bootstrap:
window.$ = window.jQuery = require('jquery')
var Backbone = require('backbone');
Backbone.$ = $;
require('../../../../bower_components/bootstrap-sass-official/assets/javascripts/bootstrap');

16
这个解决方案难道不会污染全局作用域吗?我认为 Browserify(和 RequireJS)背后的一个理念是尽量减少全局变量,只向需要它们的人暴露依赖项。 - Ziggurat
非常感谢!我知道Ziggurat在说什么,但是经过几天的折腾,我终于成功了! - Zacho
@Ziggurat 这就是 jQuery 的作用 - 将 $ 分配给 window。 - user626776
2
@Ziggaurat 是的,它正在污染全局窗口范围。是的,它违背了commonJS的概念。我希望bootstrap是作为一个模块编写的,但它不是,而我们中的一些人仍然需要使用它。由于bootstrap期望jQuery在全局范围内,作为工程师,我们真的没有太多可以做的;但就hack而言,这个并不算太糟糕。 - Jesse Greathouse
1
require('jquery') 后面缺少分号吗? - YPCrumble

11

我遇到了同样的问题:Bootstrap在NPM中可用,但未作为Common JS模块公开。我采取的方法是:

  1. 临时设置window.$window.jQuery
  2. 通过require方式加载Bootstrap.js
  3. 恢复window.$window.jQuery的值

我把下面的代码放进了一个名为bootstrapHack.js的模块中,并在应用程序的根目录中的任何其他代码运行之前要求它。

var jQuery = require('jquery');
window.$ = window.jQuery = jQuery;

require('bootstrap');

jQuery.noConflict(true);

如果你只使用一两个Bootstrap组件,可以单独引入它们并减小文件大小。在这种情况下,只需引入modal和tooltip。

var jQuery = require('jquery');
window.$ = window.jQuery = jQuery;

require('bootstrap/js/tooltip');
require('bootstrap/js/modal');

jQuery.noConflict(true);

这应该是被接受的答案,因为Ian Lim的答案是一个丑陋的hack,污染了全局命名空间。 - ooxi

3

更好的方法是使用atomify插件。这将帮助您从npm模块中解析jQuerybootstrap.jsbootstrap.css

var gulp = require('gulp');
var atomify = require('atomify');

gulp.task('default', function () {
  atomify.css('less/main.less', 'dist/bundle.css');
  atomify.js('js/index.js', 'dist/bundle.js');
});

您需要在您的less/css文件中@import引入bootstrap。

@import 'bootstrap';
@import './other.less';

@dark : #999;

body {
  background-color : @dark;
}

在您的js文件中,还需要require()引入bootstrap。

var $ = jQuery = require('jQuery')
require('bootstrap');
var other = require('./other')

console.log(typeof $().modal);
console.log(other());

module.exports = function() {
  console.log('Executed function xyz');
}

Github 存储库中有一个完整的示例。


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