Categorías: buenas practicas javascript

Integrando RequireJS en SharePoint

Tal y como se comunicaba en el anuncio oficial de la nueva versión de SharePoint, el tipo de desarrollador de SharePoint ha ido evolucionando desde un especialista en backend (código servidor) que dominaba como la palma de su mano un lenguaje como C# a un desarrollador más «web» (front-end) que tiene que conocer HTML5, JavaScript y CSS3.

Este cambio es debido a que cada vez es mayor el peso que tiene el navegador y la rapidez que proporcionan estos lenguajes. Motivados por este cambio, hemos visto cómo podemos utilizar diversos frameworks JavaScript dentro de SharePoint. Sin embargo, para los desarrolladores, entre los que me incluyo, a pesar de adaptarnos e intentar obtener las bondades de JavaScript (que las tiene y muchas) siempre echamos en falta algo de nuestro habitat natural. Este caso seguro que os suena:

  • Utilizamos JQuery para manejar los elementos de la página.
  • Hacemos uso de Mustache para mostrar una lista de resultados.
  • Incorporamos Blackbone para obtener un patrón MVC para poder tener organizada como toca nuestra aplicación.
  • Incorporamos Knockout con el fin de tener un patrón MVVM en algunos formularios.

Y en más de una ocasión hemos tenido que acordarnos que no podemos subir de versión el JQuery porque si no, la versión de Mustache no funciona, o que no podemos utilizar esta versión de Blackone porque implica subir la versión de JQuery. El resultado es que toda esta gestión en un proyecto más o menos grande hace que sea poco menos que imposible y cada cosa que añadamos tengamos que rezar y esperar que nuestra aplicación siga funcionando como hasta ese momento.

Esto en el entorno .NET lo podemos solucionar con Nuget que es el encargado de gestionar las dependencias entre las diversas librerías que componen nuestro proyecto. Pues bien, dicha funcionalidad (entre otras) es la que nos proporciona RequireJS.

RequireJS es una libreria JavaScript que se se encarga de cargar y gestionar las dependencias de nuestras librerias JavaScript. Lo que mejora la calidad de nuestro código y además hace que nuestra página se cargue mucho más rápida (ya que se encargará de descargar las librerias JavaScript de forma asincrona y bajo demanda).

Con RequireJS los archivos javascript se organizan en módulos y estos pueden tener dependencias sobre otros; todos los archivos javascript necesarios son cargados por RequireJS de forma asíncrona. Haciendo uso de RequireJS en la página web, solo será necesario incluir un único javascript, que será el de RequireJS, en la propia etiqueta script y con el atributo data-main le indicaremos el módulo del que va a hacer uso la página. El resto de módulos se cargarán como dependencias del módulo que especifiquemos en el atributo data-main.

Nuestra aplicación solo tendrá una llamada, en este caso, a nuestra libreria requirejs en la que le indicaremos cuál es el fichero JavaScript donde tenemos introducidas las dependencias.

<script src="js/require.js" data-main="js/app"></script>

El fichero app.js tendra la siguiente forma:

requirejs.config({
  baseUrl: 'js/libs',
  paths: {
    app: '../app',
    encender: '../encender/encender',
    jquery: 'jquery/dist/jquery',
    Ractive: '../ractive/Ractive',
    'amd-loader': 'requirejs-ractive/amd-loader',
    rv: 'requirejs-ractive/rv',
    rvc: 'requirejs-ractive/rvc',
    'ractive-backbone': 'ractive-backbone/Ractive-backbone',
    Backbone: 'backbone/backbone',
    'deep-model': 'backbone-deep-model/distribution/deep-model',
    'jquery-ui': 'jquery-ui/ui/jquery-ui',
    underscore: 'underscore/underscore'
  },
  map: {
    '*': {
      'backbone': 'Backbone'
    }
  },
  shim: {
    'underscore': {
      exports: '_'
    },
    'Backbone': {
      deps: ['underscore', 'jquery'],
      exports: 'Backbone'
    },
    'deep-model':{
      deps: ['Backbone']
    },
    'ractive-backbone':{
      deps: ['Ractive', 'Backbone']
    },
    'rvc': {
      deps: ['ractive-backbone', 'deep-model']
    },
    'jquery-ui': {
      exports: '$',
      deps: ['jquery']
    }
  },
  callback: function(){}
});

if (typeof booksapp === 'undefined'){
  var booksapp = {
    render: {
      main: "#render-main"
    }
  };
}

requirejs(['jquery', 'Ractive', 'Backbone', 'encender', 'app/books'], function($, Ractive, Backbone, encender, books){

  var Router = Backbone.Router.extend({

    routes: {
      "":             "home",   // #
      "books":        "books",  // #books
      "books/:id":    "books"   // #books/1234
    },

    home: function() {
      console.log("Home");
      new Ractive({
        el: booksapp.render.main,
        template: '#template-home',
        data: {
          name: 'Books'
        }
      });
    },

    books: function(id) {
      if(id){
        //retrieve one particular book
        booksapp.books.show(id);
      } else{
        //retrieve collection & display
        if(!booksapp.books){
          booksapp.books = new books.Collection();
          booksapp.books.retrieveAll();
        } else{
          booksapp.books.showAll();
        }
      }
    }

  });

  $(function(){
    booksapp.router = new Router();
    encender.delegateNavigation('/', booksapp.router);
    /*
     * If your application is not being served from the root url / of your domain,
     * be sure to tell History where the root really is, as an option:
     * Backbone.history.start({pushState: true, root: "/public/search/"})
     */    Backbone.history.start({pushState: true});

    var forward = encender.getQueryParams()['forward-url'];
    if (forward){
      booksapp.router.navigate(forward, {trigger: true});
    }

  });

});

Integrando RequireJS en SharePoint

Require está muy bien para cualquier desarrollo Web, pero ¿cómo lo puedo utilizar dentro de SharePoint?.

SharePoint por defecto ya tiene un cargador de sus ficheros JavaScript, que desconozco el orden en el que se cargan y las dependencias entre los mismos, debido a que hay muy poca/nula información al respecto. Si yo añado RequireJS, tal y como explico en la parte de arriba, hay algunos casos en los que no funciona. ¿Por qué?

En muchos casos, nosotros hacemos uso del modelo de objetos de cliente de JavaScript de SharePoint por lo que si en nuestro código llamamos al CSOM antes de que tengamos cargada la librería sp.js no podremos consultar los datos de la lista.

Solución
Para hacer uso de CSOM Microsoft recomienda que antes de hacer cualquier petición comprobemos que tengamos cargada la libreria sp.js. Para ello, tenemos que utilizar la función SP.SOD.executeFunc que se recomienda en su versión 2013 o el ExecuteDelayUntil en la versión 2010 antes de realizar cualquier petición el modelo de objetos de cliente de SharePoint y no se produzca ningún error. Pero, si por el contrario, en lugar de utilizar el CSOM, utilizamos los endpoint Rest que nos proporciona SharePoint o bien consumimos un servicio propio, no tenemos este problema.

Conclusión

En SharePoint podemos hacer uso de los elementos más novedosos y aunque aparentemente hay un camino rápido para hacer las cosas, en muchas ocasiones hacer las cosas rápidas no implica que sea la mejor forma de realizarlas. En nuestra plataforma preferida se pueden hacer las cosas igual de bien y de mal que en otras plataformas. Esos tabús de que SharePoint es una plataforma que solamente se puede trabajar de una forma anticuada y no adecuada no es la correcta, y dista mucho de la realidad con la que nos encontramos día a día.

Compartir
Publicado por
Adrián Díaz

Este sitio web utiliza cookies para que tengas la mejor experiencia de usuario. Si continuas navegando, estás dando tu consentimiento para aceptar las cookies y también nuestra política de cookies (esperemos que no te empaches con tanta cookie 😊)