¿Cómo puedo administrar el alias de ruta relativa en varios paquetes de grunt-browserify?


Esto es tad long pero necesitaré el ejemplo de código para ilustrar mi confusión. Después de lo cual estoy interesado en la respuesta para lo siguiente:

  1. ¿Cómo uso require('module') en lugar de require('../../src/module') o require('./module')?
  2. ¿Cómo reutilizo ./index.js en spec/specs.js sin duplicar el trabajo? (Y evitar que src/app.js se ejecute ya que es un módulo de entrada).

Ya he comenzado varios proyectos basados en navegadores y me encanta browserify y grunt. Pero cada proyecto muere en el mismo punto en mi curva de desarrollo / aprendizaje. Una vez que agrego pruebas a la mezcla y tengo que administrar dos browserify paquetes (app.js y spec/specs.js), todo el sistema se desmorona. Voy a explicar:

Utilizo grunt-browserify y establezco mi directorio inicial:

.
├── 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. Utiliza un archivo de entrada (src/app.js) y hace un recorrido de código para agrupar todos los módulos requeridos.
  2. Usa browserify-shim para alias jquery.
  3. Es solo alias a jquery-ui sin cuña (requerido después de que var $ = require('jquery')).
  4. Utiliza todos los archivos helper y spec en spec/src como módulos de entrada.

Paso a través de mi configuración:

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

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

Feliz

Ahora añade 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');

Feliz

Ahora agrega especificaciones:

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!!!
});

Sad

Para resumir: ¿Cómo I...

  1. Use require('module') en lugar de require('../../src/module') o require('./module')?
  2. reutilizar ./index.js en spec/specs.js sin duplicar el trabajo? (Y evitar que src/app.js se ejecute ya que es un módulo de entrada).
Author: Sukima, 2013-11-23

4 answers

Estas respuestas dependen de cómo se configure el resto del proyecto, pero tal vez sea un buen punto de partida. También, usted tendrá que utilizar la versión beta v2 actual de grunt-browserify para que esto realmente funcione (npm install grunt-browserify@2).

1.

Puede usar aliasMapping para crear algunos alias dinámicos para sus módulos. Solo para mayor claridad, vamos a mover todos sus módulos a src/modules/. Entonces, la configuración de aliasMapping podría ser algo como esto:

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

Supongamos que usted tiene un módulo en src/modules/magic/stuff.js, entonces se puede requerir de esta manera, independientemente de donde el .el archivo js que está haciendo el require se encuentra:

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

2.

No estoy seguro de esto. La estructura de tu proyecto muestra un spec/index.js, pero mencionas spec/specs.js. ¿Se supone que son el mismo archivo?

De todos modos, ¿de qué trabajo duplicado estás hablando? Porque ./index.js tiene un archivo de entrada diferente a spec/index.js. Si está buscando una manera de incluir ./index.js en specs/, entonces tal vez pueda copiarlo antes de ejecutar las pruebas en lugar de construirlo desde cero.

 4
Author: Joni Bekenstein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-01 12:42:27

Respuesta simple:

Lo más simple es usar la opción paths de browserify. Lo uso durante algunos meses con gran éxito. Incluso he hecho un kit de inicio que utiliza esta característica: https://github.com/stample/gulp-browserify-react-phonegap-starter

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

Rutas - require.array de rutas a utilizar si no se encuentra nada en el node_modules recursive walk

Si tiene un archivo en src/js/modulePath/myModule.js esto no le permitirá escribir require("myModule") en todas partes, sino más bien require("modulePath/myModule"), desde cualquiera de sus otros archivos fuente.

¿Opción obsoleta?

¡No lo parece!

El algoritmo de resolución del módulo Browserify refleja el algoritmo de resolución en NodeJS. La opción paths de Browserify es por lo tanto el espejo del comportamiento de la variable env NODE_PATH para NodeJS. El autor de Browserify (subestack) afirma en este tema que la opción NODE_PATH está obsoleta en NodeJS y, por lo tanto, también está obsoleta en Browserify y podría ser eliminado en las próximas versiones.

No estoy de acuerdo con esta afirmación.

Ver la documentación NODE_PATH. No se menciona que la opción está en desuso. Sin embargo, todavía hay una mención interesante que hace en la dirección de la afirmación de substack:

Le recomendamos encarecidamente que coloque sus dependencias localmente en node_modules carpetas. Se cargarán más rápido y de forma más fiable.

Y esta pregunta tiene publicado en 2012 en la lista de correo.

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

Y si algo no se elimina en el algoritmo de resolución de NodeJS, no creo que se elimine pronto de Browserify:)

Conclusión

Puede usar la opción paths o poner su código en node_modules como la documentación oficial y Browserify autor recomienda.

Personalmente, no me gusta la idea de poner mi propio código en node_modules ya que simplemente mantengo toda esta carpeta fuera de mi control de fuente. Utilizo la opción paths durante algunos meses y no tuve ningún problema en absoluto, y mi velocidad de compilación es bastante buena.

La solución del subestack de poner un enlace simbólico dentro de node_modules podría ser conveniente, pero desafortunadamente tenemos desarrolladores trabajando con Windows aquí...

Sin embargo, creo que hay un caso en el que no desea usar la opción paths : cuando está desarrollando una biblioteca publicada en un repositorio NPM que será requerida por otras aplicaciones. Usted realmente no quiero que estos clientes de la biblioteca tengan que configurar la configuración de compilación especial solo porque quería evitar el infierno de ruta relativa en su lib.

Otra opción posible es usar remapificar

 30
Author: Sebastien Lorber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:01:37

Todas las respuestas aquí sobre alias y opts.paths/$NODE_PATH no son geniales porque ese enfoque es una parte obsoleta del sistema de módulos en node y browserify, por lo que podría dejar de funcionar en cualquier momento.

Debe aprender cómo funciona el algoritmo node_modules para que pueda organizar eficazmente su código de una manera que funcione bien con los directorios anidados node_modules.

Hay una sección en el manual de browserify que cubre evitar ../../../../../../.. relativo problemas de ruta. Se puede resumir como:

  • Ponga su código modular interno en node_modules/ o node_modules/app para que pueda require('yourmodule') o require('app/yourmodule') dependiendo de cuál prefiera.
  • Puede usar un enlace simbólico si está desarrollando para plataformas que no son Windows y eso es lo que prefiere.

No use opts.path/$NODE_PATH. Hace que su proyecto:

  • depende implícitamente de una configuración o ajuste de entorno no obvio
  • más difícil de hacer trabajar tanto en el nodo y el navegador
  • vulnerable a los cambios en el sistema de módulos ya que las rutas de array están obsoletas en node y browserify
 7
Author: substack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-13 21:47:08

Creo que la mejor manera absoluta de ir es, como señala Sebastien Lorber, estableciendo el camino en su llamada de browserify a través de una tubería.

Pero con la última versión de browserify, (a partir de este momento, es decir [email protected]) la variable path almacena las solo rutas que Browserify utilizará para su proceso. Por lo tanto, establecer la variable paths excluirá, digamos... sus carpetas globales para el nodo, por lo que puedo decir. Como resultado, necesitarás una tarea de Gulp que se parezca a esto:

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);
    });
});
 1
Author: Chronotope,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-07-22 18:15:00