我有一个骨干应用程序正常运行。它意味着在第3页中用作小部件。不幸的是,我刚刚意识到其中一个页面已经加载了Backbone / underscore。
我收到如下错误:
Uncaught TypeError: Cannot read property 'extend' of undefined
通常在先前未加载下划线时出现。
我的典型视图是这样的:(正常的骨干视图)
./ view1.js
var Backbone = require('backbone')
var _ = require('underscore')
var $ = require('jquery')
Backbone.$ = $
module.exports = Backbone.View.extend({
events: {
},
initialize: function () {
},
render: function () {
}
})
然后我只需要打电话:
var View1 = require('view1')
var view1Instance = new View1(...)
感谢您的帮助:)
调查后编辑:
在运行调试器时,Backbone
变量似乎是一个空对象而不是Backbone。好像require('backbone')
刚刚返回{}
EDIT2: 它似乎与此问题有关:https://github.com/substack/node-browserify/issues/790
答案 0 :(得分:7)
Backbone和Requirejs(as indicated by thlorenz here)
的问题
- backbone在查找module.exports
之前查找define
- requirejs使用全局变量,这不是一个好习惯,在这种情况下会导致问题,因为它会影响在同一个变量中运行的所有内容 浏览器标签
他建议将所有内容都包装在作用域中并隐藏define
函数。
他还有一个工具来做到这一点。browserify-shim
但是我没有使用它,而是使用Browserify的postBundleCB选项:(对同事来说)。
在我的Gruntfile
:
browserify: {
dist: {
src: ['src/app/app.js'],
dest: 'www/app.js',
options: {
postBundleCB: function (err, src, next) {
return next(null, '(function () { var define = undefined; '+src+' })();')
}
}
}
},
这解决了我的问题:)
我没有尝试使用browserify-shim,所以我对此并不了解。
答案 1 :(得分:3)
如果有人使用gulp和官方浏览器(因此postBundleCB不可用),我使用gulp-wrap来包装'定义'定义:
var wrap = require('gulp-wrap');
[...]
bundler.bundle()
.on('error', swallowError)
.pipe(source(file))
.pipe(wrap('(function () { var define = undefined; <%=contents%> })();'))
.pipe(rename(renameOptions))
.pipe(gulp.dest(argv.output?argv.output:'./dist'));
答案 2 :(得分:2)
另一种解决方法是使用这样的自定义序言:
// modules are defined as an array
// [ module function, map of requireuires ]
//
// map of requireuires is short require name -> numeric require
//
// anything defined in a previous bundle is accessed via the
// orig method which is the requireuire for previous bundles
(function outer (modules, cache, entry) {
// Save the require from previous bundle to this closure if any
var previousRequire = typeof require == "function" && require;
function newRequire(name, jumped){
var oldDefine = window.define;
window.define = undefined;
if(!cache[name]) {
if(!modules[name]) {
// if we cannot find the the module within our internal map or
// cache jump to the current global require ie. the last bundle
// that was added to the page.
var currentRequire = typeof require == "function" && require;
if (!jumped && currentRequire) return currentRequire(name, true);
// If there are other bundles on this page the require from the
// previous one is saved to 'previousRequire'. Repeat this as
// many times as there are bundles until the module is found or
// we exhaust the require chain.
if (previousRequire) return previousRequire(name, true);
var err = new Error('Cannot find module \'' + name + '\'');
err.code = 'MODULE_NOT_FOUND';
throw err;
}
var m = cache[name] = {exports:{}};
modules[name][0].call(m.exports, function(x){
var id = modules[name][1][x];
return newRequire(id ? id : x);
},m,m.exports,outer,modules,cache,entry);
}
window.define = oldDefine;
return cache[name].exports;
}
for(var i=0;i<entry.length;i++) newRequire(entry[i]);
// Override the current require with this new one
return newRequire;
})
你可以像这样给浏览器这个前缀:
browserify({
prelude: fs.readFileSync(__dirname + '/src/js/prelude.js', 'utf-8'),
...
})
答案 3 :(得分:0)
这可能与某人有关,该人在具有requirejs的网站中使用browserify。临时解决方案可以是:
`.pipe(wrap('(function () { var define = undefined; <%=contents%> })();'))`
对于直接使用browserify API的用户,可以在加载我们的捆绑软件之前添加以下代码:
(function() {
if (typeof define === "function" && define.amd) {
define.amd= false;
}})();
这将允许我们继续执行,而不会破坏客户端上的代码。
我希望这会有用。