2014-09-23 13 views
2

我有一個骨幹應用程序正常運行。它旨在用作第三頁的小部件。不幸的是,我剛剛意識到其中一個頁面已經加載了Backbone /下劃線。如何解決browserify(基於Backbone的應用程序)和require.js在同一頁面上的衝突?

我得到的錯誤,像這樣的:

Uncaught TypeError: Cannot read property 'extend' of undefined 

下劃線時尚未加載之前通常出現。

我的典型視圖是這樣的:(正常骨幹視圖)

var Backbone = require('backbone') 
var _ = require('underscore') 
var $ = require('jquery') 
Backbone.$ = $ 

module.exports = Backbone.View.extend({ 

    events: { 

    }, 

    initialize: function() { 

    }, 

    render: function() { 

    } 
}) 

那麼我只需要調用它

./view1.js:

var View1 = require('view1') 
var view1Instance = new View1(...) 

感謝您的任何幫助:)

調查後編輯: 當通過運行調試器,看來Backbone變量是一個空對象而不是Backbone。彷彿require('backbone')剛剛返回{}

EDIT2: 這似乎與此問題:https://github.com/substack/node-browserify/issues/790

+0

你能給我們提供關於錯誤的更多細節嗎?它是'Backbone.View.extend'失敗了嗎? – Ben 2014-09-23 17:38:54

+0

@ben我提到的錯誤發生在'module.exports = Backbone.View.extend'(我也編輯了這個問題) – Amida 2014-09-23 18:04:37

+0

當你有循環依賴關係時,通常會出現空對象。但是在要求Backbone時不應該發生這種情況。此外,noConflict應該不重要,因爲技術上捆綁中的所有內容都會從其他環境中關閉。 – 2014-09-23 18:07:21

回答

7

與骨幹網和Requirejs問題(as indicated by thlorenz here

  • 骨幹查找define尋找前module.exports
  • requirejs使用全局變量,這不是很好的做法,在這種情況下會導致問題s因斯它影響的是,在同一 瀏覽器選項卡

他建議在範圍包裹的一切,隱藏define函數運行一切。他也有一個工具來做到這一點。 browserify-shim

但是我沒有使用它,而是來自Browserify的postBundleCB選項:(thx to a coorker)。

在我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,墊片,所以我不很瞭解。

+0

這是迄今爲止我修復requirejs與我的庫(browserified)衝突的最簡單方法。 @balazs解決方案也可以工作,但我喜歡包裝代碼的方式,而不是將任何東西放在它之前(儘管如果你已經在代碼中有一個自我執行的匿名函數,這可能是重複的)。 – Scott 2016-01-28 15:53:07

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這樣的:

browserify({ 
    prelude: fs.readFileSync(__dirname + '/src/js/prelude.js', 'utf-8'), 
    ... 
}) 
3

如果有人使用杯和官方browserify (所以postBundleCB不可用)我用gulp-wrap來包裝'define'定義:

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'));