Uploaded image for project: 'XWiki Platform'
  1. XWiki Platform
  2. XWIKI-18185

Separate the Velocity code from the JavaScript code in JavaScript files

    XMLWordPrintable

    Details

    • Difficulty:
      Unknown
    • Documentation in Release Notes:
      N/A
    • Similar issues:

      Description

      Mixing Velocity code with JavaScript code (inline) can lead to unexpected bugs because the minifier (e.g. Closure Compiler) is run at build time, before the Velocity code is evaluated. We can have two types of problems:

      • the Velocity code doesn't appear as valid JavaScript code and thus the minification fails (e.g. the Velocity code is outside of a JavaScript comment)
      • the Velocity code looks like JavaScript and the minifier rewrites it (optimizes it) and the result is no longer valid Velocity code, thus failing at runtime (when the Velocity code is evaluated)

      One solution is to try to reduce the need for Velocity code but it's not always possible to drop the Velocity code completely. The most common need for Velocity code in JavaScript is:

      • paths / URL (e.g. RequireJS configuration, application context path)
      • localization

      In this case, the solution I propose is to separate clearly the Velocity code from the JavaScript code, i.e. to avoid in-lining Velocity code within JavaScript code. One way to achieve this is to follow this pattern:

      /*!
      ## Velocity code here.
      #set ($paths = ...)
      #set ($l10n = ...)
      ...
      #[[*/
      // Start JavaScript-only code.
      (function(paths, l10n) {
        "use strict";
        ...
      // End JavaScript-only code.
      }).apply(']]#', $jsontool.serialize([$paths, $l10n]));
      

      The benefits are:

      • clear separation between Velocity and JavaScript
        • the only line where we mix Velocity with JavaScript in-line is the last one, but we know this one is safe
        • Velocity parsing is disabled within the JavaScript-only section due to the special Velocity syntax '#[[ ... ]]#'
      • the Velocity values/objects that are needed in the JavaScript code are serialized as JSON and passed as arguments to an anonymous function
      • writing unit tests for this JavaScript requires mocking only $jsontool.serialize and the Velocity values/objects

      Note that JavaScript code located in wiki pages (JSX) is not affected because in this case the minification is performed at runtime after the Velocity code is evaluated.

        Attachments

          Issue Links

            Activity

              People

              Assignee:
              mflorea Marius Dumitru Florea
              Reporter:
              mflorea Marius Dumitru Florea
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Dates

                Created:
                Updated:
                Resolved:
                Date of First Response: