2013-11-23 16 views
43

這有點長,但我需要代碼示例來說明我的困惑。這之後,我很感興趣的答案如下:如何在多個grunt-browserify軟件包中管理相對路徑別名?

  1. 我如何使用require('module')代替require('../../src/module')require('./module')
  2. 如何重複使用./index.jsspec/specs.js而不重複工作? (並防止src/app.js由於它是入口模塊而運行)。

我已經開始了幾個基於瀏覽器的項目,並且愛着browserify和grunt。但是每個項目都會在我的開發/學習曲線中死去。一旦我將測試添加到組合中並且必須管理兩個browserify捆綁包(app.jsspec/specs.js),整個系統就會崩潰。我將解釋:

我用grunt-browserify,並設置我的初始目錄:

. 
├── Gruntfile.js 
├── index.js (generated via grunt-browserify)  [1] 
├── lib 
│   ├── jquery 
│   │   └── jquery.js        [2] 
│   └── jquery-ui 
│    └── jquery-ui.js       [3] 
├── spec 
│   ├── specs.js (generated via grunt-browserify) [4] 
│   └── src 
│    ├── spec_helper.js (entry) 
│    └── module_spec.js (entry) 
└── src 
   ├── app.js (entry) 
   └── module.js 
  1. 使用一個條目文件(src/app.js),並做了代碼走捆綁所有需要模塊。
  2. 使用browserify-shim別名jquery
  3. 只是別名jquery-ui沒有墊片(需要你後var $ = require('jquery'))。
  4. spec/src中的所有幫助程序和規格文件用作輸入模塊。

我會通過我的配置步驟:

browserify: { 
    dist: { 
    files: { 
     'index.js': ['src/app.js'] 
    } 
    } 
} 

// in app.js 
var MyModule = require('./module'); // <-- relative path required?! 

快樂

現在添加的jQuery:

browserify: { 
    options: { 
    shim: { 
     jquery: { 
     path: 'lib/jquery/jquery.js', 
     exports: '$' 
     } 
    }, 
    noParse: ['lib/**/*.js'], 
    alias: [ 
     'lib/jquery-ui/jquery-ui.js:jquery-ui' 
    ] 
    }, 
    dist: { 
    files: { 
     'index.js': ['src/app.js'] 
    } 
    } 
} 

// in app.js 
var $ = require('jquery'); 
require('jquery-ui'); 
var MyModule = require('./module'); 

快樂

現在添加規格:

options: { 
    shim: { 
    jquery: { 
     path: 'lib/jquery/jquery.js', 
     exports: '$' 
    } 
    }, 
    noParse: ['lib/**/*.js'], 
    alias: [ 
    'lib/jquery-ui/jquery-ui.js:jquery-ui' 
    ] 
}, 
dist: { 
    files: { 
    'app.js': 'src/app.js' 
    } 
}, 
spec: { 
    files: { 
    'spec/specs.js': ['spec/src/**/*helper.js', 'spec/src/**/*spec.js'] 
    } 
} 

// in app.js 
var $ = require('jquery'); 
require('jquery-ui'); 
var MyModule = require('./module'); 

// in spec/src/module_spec.js 
describe("MyModule", function() { 
    var MyModule = require('../../src/module'); // <-- This looks like butt!!! 
}); 

悲傷

總結:我如何...

  1. 使用require('module')而不是require('../../src/module')require('./module')
  2. 重用./index.js in spec/specs.js沒有重複的工作? (並防止src/app.js由於它是入口模塊而運行)。

回答

4

這些答案取決於您的項目其餘部分的設置,但也許這是一個很好的起點。此外,您將需要使用grunt-browserify的當前v2測試版來實際運行(npm install [email protected])。

可以使用aliasMapping爲你的模塊創建一些動態的別名。爲了清楚起見,我們將所有模塊移動到src/modules/。然後,aliasMapping配置可以是這樣的:

options: { 
    aliasMappings: { 
    cwd: 'src', 
    src: ['modules/**/*.js'] 
    } 
} 

讓假設您在src/modules/magic/stuff.js一個模塊,那麼你可以要求它這樣,無論是在做了需要的.js文件位於:

var magicStuff = require('modules/magic/stuff.js'); 

2.

不知道這一個。您的項目結構顯示spec/index.js,但您提到spec/specs.js。他們應該是同一個文件嗎?

無論如何,你在說什麼重複的工作?因爲./index.jsspec/index.js有不同的輸入文件。如果您正在尋找將./index.js包含在specs/中的方法,那麼也許您可以在運行測試之前將其複製,而不是從頭開始構建它。

+0

'spec/index.js'與'spec/specs,js'是一個錯字。編輯的問題。謝謝你的回答。似乎真相是原始的(舊版本)沒有被設計來做這個設置。我認爲更好的問題是*應該如何組織這樣的項目?許多教程不捆綁生產腳本和測試腳本。添加testem之類的東西,難怪人們會感到困惑。我們需要一個元指南,將所有這些軟件包和諧地整合在一起。 – Sukima

+1

根本問題可能是JS生態系統的多樣性。它還很年輕。也許有一天重複的軟件包/實用程序將停止共存,其中一個將成爲解決X事務的默認資源。現在,談到JS時,至少有2/3不同的庫在做同樣的事情。所以對於像構建系統這樣的東西來說,特別難以完全不可知,並且對於所有可能的庫組合來說都很好。 –

+0

這是'aliasMappings'選項特定於'grunt-browserify'還是它是一個'browserify'隱藏選項的包裝?我試圖用['opts.basedir'](https://github.com/substack/node-browserify#var-b--browserifyfiles-or-opts)選項獲得相同的行爲,但沒有運氣。 – eightyfive

29

答案很簡單:

最簡單的方法是使用browserify的paths選項。我用了它幾個月,取得了巨大的成功。我甚至提出,使用此功能入門套件:https://github.com/stample/gulp-browserify-react-phonegap-starter

var b = browserify('./app', {paths: ['./node_modules','./src/js']}); 

路徑 - require.paths數組,如果沒有什麼是對正常 發現使用node_modules遞歸步行

如果你有src/js/modulePath/myModule.js中的文件不允許您在任何其他源文件中編寫require("myModule"),而是require("modulePath/myModule")

棄用選項?

它似乎並不如此!

Browserify模塊分辨率算法鏡像resolution algorithm in NodeJS。 Browserify的paths選項因此是用於NodeJS的NODE_PATH env變量行爲的鏡像。 Browserify作者(substack)在本SO主題中聲稱NODE_PATH選項在NodeJS中已被棄用,因此它在Browserify中也被棄用,並且可能在下一版本中被刪除。

我不同意這個說法。

請參閱NODE_PATH文檔。沒有提到該選項已被棄用。但是仍然有一個有趣的提到,確實在亞組的要求的方向:

你非常鼓勵本地將您的依賴關係 node_modules文件夾。他們將更快,更可靠地加載。

this question已於2012年發佈在郵件列表中。

Oliver Leics: is NODE_PATH deprecated? 
Ben Noordhuis (ex core NodeJS contributor): No. Why do you ask? 

如果事情不解決的NodeJS算法中移除,我不認爲它會很快從Browserify :)

結論

您可以使用paths選項刪除或者把你的代碼放在node_modules之類的官方文檔和Browserify author recommends

就個人而言,我不喜歡這個主意,把自己的代碼中node_modules我只是保持這個整個文件夾我的源代碼控制的。我在幾個月內使用了paths選項,並且根本沒有任何問題,並且我的構建速度非常好。

把一個符號內node_modules可能是方便,但不幸的是,我們已經與Windows在這裏工作的開發人員的亞組的解決方案......

我認爲不過有,你不想使用paths選項的情況下,:當您正在開發在其他應用程序需要的NPM存儲庫上發佈的庫時。你真的不希望這些庫客戶端必須設置特殊的構建配置,只是因爲你想避免lib中的相對路徑地獄。

另一個可能的選擇是使用remapify

+2

剛剛遇到這個線程,這個選項對於當前的browserify/grunt-browserify來說更好。有關它在grunt-browserify(已驗證)中的外觀示例,請參見:http://cl.ly/VXyx(注意路徑在browserify選項下) –

+0

其他人在Browserify 8.1中使用'paths'時看到了問題0.1?我一直在看「無法找到模塊」消息,並恢復到8.0.1。 – Cory

6

一切答案在這裏有關別名和opts.paths/$NODE_PATH都不是很大,因爲這種方法是在節點的模塊系統的過時的部分和browserify,所以它可能停止工作任何時候。

你應該學習how the node_modules algorithm works,這樣你就可以有效地組織你的代碼,並且可以很好地嵌套node_modules目錄。

有在覆蓋avoiding ../../../../../../..相對路徑問題browserify手冊的部分。這可以概括爲:

  • 把內部模塊化的代碼在node_modules/node_modules/app這樣就可以require('yourmodule')require('app/yourmodule'),這取決於你喜歡。
  • 如果您正在爲非Windows平臺開發,那麼您可以使用符號鏈接,而這正是您喜歡的。

請勿使用opts.path/$NODE_PATH。它使你的項目:

  • 隱式依賴於一個非顯而易見性配置或環境設置
  • 困難,使在這兩個節點和瀏覽器
  • 容易模塊系統中的變化工作,數組的路徑已被棄用在節點和browserify
+0

感謝您的見解。你知道爲什麼'opts.path'已被棄用嗎?我不喜歡使用棄用的解決方案,但我認爲這個棄用的選項比將代碼放在'node_modules'中方便得多。你知道它爲什麼被棄用嗎?任何github問題?我找不到任何 –

+0

順便說一句,在官方文檔(http://nodejs.org/api/modules.html)上,我們可以這樣讀:'爲了使模塊可用於節點REPL,它可能是有用的還要將/ usr/lib/node_modules文件夾添加到$ NODE_PATH環境變量中。由於使用node_modules文件夾的模塊查找都是相對的,並且根據調用require()的文件的實際路徑,軟件包本身可以位於任何位置。請告訴我們您在哪裏看到它已被棄用,因爲正式文檔並不反映這一點。 –

+0

好的,所以我在這裏找到了一些你在說的內容:http://nodejs.org/api/all.html#all_loading_from_the_global_folders。 '這些主要是出於歷史原因。強烈建議您將您的依賴項本地放置在node_modules文件夾中。他們會更快,更可靠地加載。「這是一個建議,但實際上並沒有說該功能已被棄用,可能會被刪除。根據這個ML討論,它也不被棄用:https://groups.google.com/forum/#!topic/nodejs/EENwg8GAJd8 –

1

我認爲最好的方法是像Sebastien Lorber指出的那樣,通過管道調用browserify來設置路徑。

但與最新版本browserify的,(因爲這一刻,這是[email protected])路徑變量存儲路徑是Browserify將用於它的進程。因此,設置路徑變量將排除說......您的節點的全局文件夾,據我所知。因此,你需要一個Gulp任務,看起來像這樣:

gulp.task('reactBuild', function() { 
    return gulp.src(newThemeJSX) 
    .pipe(browserify({ 
     debug: true, 
     extensions: ['.jsx', '.js', '.json'], 
     transform: [reactify], 
     paths: ['../base_folder/node_modules', '/usr/lib/node_modules'] 
    })) 
    .pipe(gulp.dest(newThemeBuilt)) 
    .on('error', function(error) { 
     console.log(error); 
    }); 
}); 
相關問題