domingo, 20 de setembro de 2015

Using modules outside of app root directory with WebPack

In order to evaluate different mobile UI  frameworks (Ionic, jQuery Mobile etc) i started a project with multiple client apps, each one completely independent with its own configuration. The business logic layer, a couple of Backbone models, is the only code shared by the apps.

It has the following directory structure, where the models resides in the shared folder. At the same level, there's ionic-mn folder which holds one of the mobile clients including package.json, webpack.config.js etc.


  |-shared
  |---models
  |-ionic-mn
  |---css
  |---fonts
  |---node_modules
  |-----backbone
  |---scripts

The problem started when i tried to resolve the js files in the shared folder. Reading the WebPack site i managed to do it modifying resolve.root, so i ended with the following config:

var path = require('path');

module.exports = {
    entry: "./scripts/main.js",
    output: {
        path: __dirname,
        filename: "bundle.js"
    },
    resolve: {
       root: [path.resolve('.'), path.resolve('../shared')]            
    }
};

With this i succeeded resolving the shared entity.

var OwnedSymbol = require('models/ownedsymbol');

But started  to get a different error:

ERROR in ../shared/models/ownedsymbol.js
Module not found: Error: Cannot resolve module 'backbone' in D:\repositories\sharemonitor\clients\shared\models

This occurs because ownedsymbol.js tries to resolve 'backbone' module. I looked for info in net without luck. Tried to use ProvidePlugin and also did not work. In the end i did the hard way:
    ..
    //in webpack config
    module: {
        loaders: [
          { test: require.resolve("backbone"), loader: "expose?Backbone" },
          { test: require.resolve("underscore"), loader: "expose?_" }
        ]
    ..
Yes, i took the heretic path and set Backbone and underscore to a global variable. It works but diverges from the idiomatic module usage so i tried with the imports-loader:
    ..
    //in code:
    var OwnedSymbol = require('imports?backbone=Backbone,underscore=_!models/ownedsymbol'); 
    ..
This solution would avoid the global variable issue, the only problem is that does not work. I get:

ERROR in ./~/imports-loader?backbone=Backbone,underscore=_!../shared/models/ownedsymbol.js
Module not found: Error: Cannot resolve module 'Backbone' in D:\repositories\sharemonitor\clients\shared\models

While i don't discover a better solution, i'll stick to the expose/global path. If the price to start coding is being a herege...

Update


The WebPack developer sokra pointed at gitter to try resolve.fallback, so i did:

   
  resolve:
     {
       root: [path.resolve('.'), path.resolve('../shared')],      
       fallback: __dirname + '/node_modules'
     }

With this configuration in place the build worked but with duplication of some modules. I managed to resolve the duplication using npm dedupe plus WebPack dedupe plugin.
So far, so good, now i have the option to stay clean avoiding global variables, at the cost of some extra configuration.

Um comentário:

  1. Wynn Casino, Las Vegas - MapYRO
    Wynn Casino, Las Vegas, NV, United 양주 출장안마 States. 논산 출장마사지 MapYRO provides real-time driving 포항 출장안마 directions 계룡 출장샵 to 경산 출장샵 casinos and other facilities located in Las Vegas, NV.

    ResponderExcluir