nodejs路徑引用問題

nodejs路徑引用問題

  1. gulp-babel的引用路徑問題node

  2. gulp src 文件流路徑es6

  3. require('xx') 路徑問題shell

本文主要講述了編寫外部構建工具中gulp-babel中依賴es2015插件失敗問題、gulp.src路徑問題以及require('xx')的路徑問題。npm

gulp的src做用是引入所須要的流,且其使用了node-glob模塊實現了文件匹配,json

gulp.src(globs[, options])

其中options對象中的屬性除了node-glob可使用的除外,還額外增長了options.buffer ,options.read, options.base,關於這三個額外的屬性做用能夠查看 gulp apigulp

這裏主要介紹node-glob中的cwd屬性api

options.cwd
Default is process.cwd()

不知道你們以前有無疑惑,咱們把gulpfile文件放在獨立於項目文件的目錄中,相似數組

~/Desktop/GIT/dada/lib/dada-task/gulpfile.jsbabel

在這個文件中分別定義了項目構建相關的taskless

gulp.task("less", function() {
    gulp.src('./src/less/*.less', {
      cwd: __dirname
    })
      .pipe(less())
      .pipe(gulp.dest(srcPath.CSS)) //無視路徑
      .pipe(browserSync.stream()); //無視路徑
  })

接着咱們在項目目錄中調用構建命令

//項目目錄cwd
/Users/lvdada/Desktop/WorkGit/05-marketing

//調用
node ~/Desktop/GIT/dada/lib/dada-task/gulpfile.js

結果成功了,gulp.src('./src/less/*.less') 取的是相對路徑,照理說應該是相對於gulpfile.js文件纔對,結果取到的文件流是項目文件中的,這就要歸功於node-glob中的cwd屬性了,默認狀況下,gulp.src取到的文件都是相對process.cwd()的,也就是在命令工具中調用shell命令時的路徑。在項目目錄中調用命令的時候就至關於項目目錄。

可是這樣有個問題

.pipe(babel({
      presets: ['es2015']
    }))
    .pipe(gulp.dest('./src/js'))

此段task片斷是對gulp-babel對es6的編譯,須要es2015這個babel插件,此時babel的默認取文件流路徑是相對於process.cwd()的,
這就致使了會在項目目錄中尋找es2015babel插件,確定的是是找不到的。

通過google發現瞭解決辦法,

.pipe(babel({
      presets: ['babel-preset-es2015'].map(require.resolve)
    }))
    .pipe(gulp.dest('./src/js'))

對presets數組進行遍歷並執行require.resolve方法
hack來源

至於require.resolve的做用,須要瞭解一下node模塊require()工做原理。參考阮一峯

代碼中執行require(X)時,會按照下面的順序處理引用,分紅兩種類型:

(一)第一種是帶相對路徑的引用,好比./bar.js ../bar

其中又分兩種狀況,

  • 當作具體文件進行引用

有具體文件後綴的直接引用(相似bar.js),沒有後綴標識的會一次查找下面文件後綴類型,只要存在就返回。

- bar
- bar.js
- bar.json
- bar.node
  • 當作具體目錄進行引用

此時加載器會將bar當作一個目錄,並依次查找bar目錄下的文件,只要找到其中之一就返回該文件。

bar/package.json(main字段)(main字段中有引用的文件地址)
bar/index.js
bar/index.json
bar/index.node

(二)第二種是不帶相對路徑的引用,好比require('fs') require('gulp-if')

  • 引用是內置模塊時,好比fs,直接加載fs模塊。

  • 引用不是內置模塊,好比gulp-if

則在當前路徑的父目錄逐級向上尋找node_modules文件夾,而後把gulp-if先當作具體文件按照上面的方法查找文件,若找不到,再將gulp-if當作具體目錄進行查找。具體的向上查找路徑集合能夠經過module.path查詢。
假設一個文件test.js

console.log('module.paths: ', module.paths);

在當前目錄執行node test.js,會輸出:

module.paths:  [ '/Users/lvdada/Desktop/GIT/test/dada-test/src/js/node_modules',
 '/Users/lvdada/Desktop/GIT/test/dada-test/src/node_modules',
 '/Users/lvdada/Desktop/GIT/test/dada-test/node_modules',
 '/Users/lvdada/Desktop/GIT/test/node_modules',
 '/Users/lvdada/Desktop/GIT/node_modules',
 '/Users/lvdada/Desktop/node_modules',
 '/Users/lvdada/node_modules',
 '/Users/node_modules',
 '/node_modules' ]

若在文件系統中查詢不到require的模塊,則會在全局模塊路徑中查找。

// npm root -g

/usr/local/lib/node_modules

上面介紹的文件查詢方法是基於相對路勁的,當模塊加載器要加載模塊須要肯定模塊的絕對地址。

Module._resolveFilename() // 獲得模塊的絕對地址,並由此地址加載模塊

最後node暴露出來的一個屬性和一個方法能夠獲得模塊的絕對地址:

module.filename ;
var filename = request.resolve('./bar.js');

回到以前的問題,在gulp-babel中指定的babel插件沒法有效加載。

.pipe(babel({
      presets: ['babel-preset-es2015'].map(require.resolve)
    }))
    .pipe(gulp.dest('./src/js'))

使用require.resolve進行路徑的查找匹配,最後得出正確的絕對路徑。

原創文章!歡迎轉載

相關文章
相關標籤/搜索