2015-05-05 58 views
7

'u kullanarak bir takma ad modülünü dinamik olarak gerektiriyor Bir grup modül takma adını web paketi üzerinden resolve.alias aracılığıyla yapıyorum. Sonra, benim app kodunda, ben bir takma ad içeren bir değişken kullanarak bu modüllerden birini gerektirecek istiyorum: Ne yazıkWebpack

var module = require(moduleAlias); 

, bu komut dosyasının dizin ve onun soyundan gelen her şeyi içeren bir "bağlam modülü" yaratır Bu özel durumda ne yaptığımı değil. Ayrıca, kodumun hiçbir yerinde, tüm takma adlara sahip modüllere açık bir şekilde ihtiyaç duyduğumdan, uygulamamın içine yerleştirilmiyorlar.

İki soru: Bütün ad verilmiş modüller benim koduyla birlikte sunulan

  1. nasıl emin olabilirim?
  2. Takma ad içeren bir değişken kullanarak bunlara nasıl erişirim?

Teşekkürler!

+0

Neden içe aktarma dinamik olmalı? İçeriği biraz daha iyi tarif edebilir misiniz? –

+0

Gerekli olması gereken modüller, sunucudan gelen verilere bağlı olarak değişir. Verdiğim örnekte, 'moduleAlias' değeri sunucudan geliyor. – Aaronius

+0

Bağımlılık dinamik olduğu için, '$ script' gibi ayrı bir yükleyiciden geçmeniz gerekebilir. [Sayı 150] bölümüne bakın (https://github.com/webpack/webpack/issues/150). –

cevap

8

Bu yalnızca sorunun ikinci kısmını cevap verir: Eğer takma ile modülünü birlikte gelmiş ve o adlar bir bağlamdan requirable olmak istiyorsanız: Bildiğim kadarıyla

, yapmanın hiçbir resmi yolu yoktur webpack ile. Ben Düğüm 4 ile çalışan bir eklenti oluşturdu (saf ES5 kullanmak istiyorsanız uyarlayabilirsiniz), herhangi bir bağlama adların listesini katacak:

'use strict'; 

class AddToContextPlugin { 
    constructor(extras) { 
    this.extras = extras || []; 
    } 

    apply(compiler) { 
    compiler.plugin('context-module-factory', (cmf) => { 
     cmf.plugin('after-resolve', (result, callback) => { 
     this.newContext = true; 
     return callback(null, result); 
     }); 

     // this method is called for every path in the ctx 
     // we just add our extras the first call 
     cmf.plugin('alternatives', (result, callback) => { 
     if (this.newContext) { 
      this.newContext = false; 

      const extras = this.extras.map((ext) => { 
      return { 
       context: result[0].context, 
       request: ext 
      }; 
      }); 

      result.push.apply(result, extras); 
     } 
     return callback(null, result); 
     }); 
    }); 
    } 
} 

module.exports = AddToContextPlugin; 

Bu kullanabilirsiniz nasıl:

webpack({ 
     /*...*/ 
     resolve: { 
     alias: { 
      'alias1': 'absolute-path-to-rsc1', 
      'alias2$': 'absolute-path-to-rsc2' 
     } 
     }, 
     plugins: [ 
     new AddToContextPlugin(['alias1', 'alias2']) 
     ] 
    }) 

Ve aşağıdaki kodu olarak neden oluşturulan:

function(module, exports, __webpack_require__) { 

    var map = { 
     "./path/to/a/rsc": 2, 
     "./path/to/a/rsc.js": 2, 
     "./path/to/another/rsc.js": 301, 
     "./path/to/another/rsc.js": 301, 
     "alias1": 80, 
     "alias2": 677 
    }; 
    function webpackContext(req) { 
     return __webpack_require__(webpackContextResolve(req)); 
    }; 
    function webpackContextResolve(req) { 
     return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }()); 
    }; 
    webpackContext.keys = function webpackContextKeys() { 
     return Object.keys(map); 
    }; 
    webpackContext.resolve = webpackContextResolve; 
    module.exports = webpackContext; 
    webpackContext.id = 1; 

} 
+0

Çok güzel @JBE. Projemizin gereksinimleri değiştiği için bunu denemedim ama diğer cevapların yokluğunda bunu doğru olarak işaretleyeceğim. Teşekkür ederim. – Aaronius

5

buldum en temiz çözüm varsayılan modülü Kimliği sistemi üzerine yazılmasıdır. Webpack varsayılan olarak dizi dizinini kullanıyor gibi görünüyor. Dosya yolunun takma ad modülünde olup olmadığını görmek için bir kontrol yapıyorum, daha sonra onun kimliğini bu değere ayarlıyorum.

ben senkron dinamik yapmak için gerekli zaman kodunda Bu şekilde bir takma adla gerektirir

, ben bu özel yöntemler (__webpack_require__) kullanılarak toplam kesmek __webpack_require__(alias)

yapabilirdi, ama geçici olarak görüyoruz codebase'imi düzgün bir şekilde uyumsuz dinamik gereksinime geçirene kadar düzeltin ya da birçok requireJS kod tabanı gibi her yerde takma ad yerine doğru şekilde kullanın.

var path = require('path'); 
var _ = require('lodash'); 

function NamedAliasModules(){};  

NamedAliasModules.prototype.apply = function(compiler){ 
    compiler.plugin('compilation', function(compilation){ 
     compilation.plugin("before-module-ids", function(modules) { 
      modules.forEach(function(module) { 
       if(module.id === null && module.libIdent) { 
        var id = module.libIdent({ 
         context: compiler.options.context 
        }); 
        var fullpath = path.resolve(__dirname, id); 

        if (_.has(aliasLookup, fullpath) || _.has(aliasLookup, fullpath.replace(/\.js$/,''))){ 
         id = aliasLookup[fullpath] || aliasLookup[fullpath.replace(/\.js$/, '')]; 

         module.libIdent = function(){ 
          return id; 
         } 

        } 
        module.id = id; 
       } 
      }, this); 
     }.bind(this)); 
    }.bind(this)); 
}