Meteor

Last updated: 4 June 2021

Framework version tested: 1.6 ● 1.11.0

Github: Meteor repository

Introduction

Meteor, or MeteorJS, is a free and open-source isomorphic JavaScript web framework written using Node.js. Meteor allows for rapid prototyping and produces cross-platform (Android, iOS, Web) code. It integrates with MongoDB and uses the Distributed Data Protocol and a publish-subscribe pattern to automatically propagate data changes to clients without requiring the developer to write any synchronization code. On the client, Meteor can be used with its own Blaze templating engine, as well as with the Angular or React frameworks.

The purpose of this document is to explain how to integrate Jscrambler with Meteor.

This document assumes you already have some knowledge of the framework and how to build a project. Still, if you have any doubt please read this official guide.

Example app

In this document we will use as reference a TODO App developed using Meteor. You can check this tutorial to learn more about how to create an app. Otherwise you can skip the step above and download the app.

To install dependencies and run the application please run the following commands

meteor npm install
meteor

Integration

Before starting the integration process, some information about Meteor's specific folder structure and build process is described bellow:

Meteor folder Structure

  • client - files that will be available only on the client side

  • server - files that will be available only on the server side

  • public - files that will be served as is to the client e.g. assets like images, fonts, etc

  • lib - Any folder named lib (in any hierarchy) will be loaded first

    Any other folder name will be included in both client and server and will be used for code-sharing.

  • Meteor build process*

    Meteor uses the build tool Isobuild to compile and bundle the application. We can create custom plugins that integrate into Meteor's build process in different phases. There are 3 phases when a plugin can run: linting, compilation, and minification.

  • Linting Phase: Linters are programs that check the code for undeclared variables or find code that doesn’t correspond to certain style guidelines. Some of the popular examples of linters are JSHint and ESLint.

  • Compilation Phase: Compilers are programs that take the source files and output JavaScript or CSS. Examples of compiler plugins are CoffeeScript, Babel.js, JSX compilers, Pug templating compiler and others.

  • Minification Phase: Minifiers run last after the sources have been compiled and JavaScript code has been linked. Minifiers only run for the client programs. This is where Jscrambler fits.

Integrating with Jscramber

In order to integrate Jscrambler, we will register a Minifier into the build process of Meteor. To do that, we need to create a local package that will act as a minifier in our app. By default, Meteor uses a standard JavaScript minifier that bundles your js files (standard-minifier-js). Meteor does not support multiple minifiers, therefore we need to replace the current minifier with a custom one.

We will extend the default minifier plugin in order to integrate Jscrambler into it and still have its benefits of bundling all the files together.

Step 1

Create a custom local package.

  • Create a folder named packages in your app (if you don't already have one)

  • Get the files for the plugin

  • Place them in a folder named jscrambler inside packages

  • Structure*

    App
    +___.meteor/
    +___.testing/
    +___client/
    +___i18n/
    +___imports/
    +___packages/
    |     |
    |     +___jscrambler/
    |           |   package.js
    |           +___plugin/
    |           |     |   jscrambler_config.json
    |           |     |   minify-js.js
    |           |     |   stats.js
    |           |     |   utils.js
    |           |     |   visitor.js
    +___public/
    | ...

package.js - has the information about the package.

// Information about this package:
Package.describe({
  // Short two-sentence summary
  summary: 'An extension of standard-minifier-js that protects your code using Jscrambler',
  // Version number
  version: '1.0.0',
  // Optional, default is package directory name
  name: 'jscrambler:protect'
});

// Depends on isobuild:minifier-plugin
Package.onUse((api) => {
  api.use('isobuild:[email protected]');
});

// Register a build plugin
Package.registerBuildPlugin({
  name: 'protectWithJscrambler',
  use: [
    '[email protected]',
    'babel-compiler',
    'ecmascript'
  ],
  sources: [
    'plugin/minify-js.js',
    'plugin/stats.js',
    'plugin/visitor.js',
    'plugin/utils.js'
  ],
  npmDependencies: {
    jscrambler: '5.2.19',
    deasync: '0.1.11'
  }
});

plugin/ - Folder with the code of the plugin itself. It will minify and protect your JavaScript files. You can edit the files inside it to comply with your app specific needs.

plugin/minify-js.js - This is where we register the minifier and do the processing of all the js files of the app. We have a function that decides if a file should be protected or not. Feel free to modify it in order to meet your protection needs.

  // Check if a file should be protected
  // You can use a regex to select which files to protect,
  // in this example we are only protecting app/app.js (a bundle with the js files of our app)
  // We can also protect external packages, their path is "packages/*.js"
  function shouldProtect (filePath) {
    return filePath === 'app/app.js';
  }

Step 2

The file jscrambler_config inside jscrambler/plugin/ has the configuration used in Jscrambler. You need to replace the placeholders (ACCESS_KEY, SECRET_KEY, and APP_ID) with the ones in your account. You can read more about the configuration file in the Jscrambler Client GitHub page

{
  "keys": {
    "accessKey": <ACCESS_KEY>,
    "secretKey": <SECRET_KEY>
  },
  "host": "api4.jscrambler.com",
  "port": 443,
  "applicationId": <APP_ID>,
  "params": [
    {
      "name": "whitespaceRemoval"
    },
    {
      "name": "identifiersRenaming",
      "options": {
        "mode": "SAFEST"
      }
    },
    {
      "name": "dotToBracketNotation"
    },
    {
      "name": "deadCodeInjection"
    },
    {
      "name": "stringConcealing"
    },
    {
      "name": "functionReordering"
    },
    {
      "options": {
        "freq": 1,
        "features": [
          "opaqueFunctions"
        ]
      },
      "name": "functionOutlining"
    },
    {
      "name": "propertyKeysObfuscation"
    },
    {
      "name": "regexObfuscation"
    },
    {
      "name": "booleanToAnything"
    }
  ]
}

Step 3

Due to Meteor not allowing more than one minifier with the same target (in this case JavaScript), we will remove the default (standard-minifier-js) and add our plugin in its place.

  meteor remove standard-minifier-js
  meteor add jscrambler:protect

Step 4

All done! If you run your app in production mode, your code will be protected by Jscrambler. You can do it by running:

meteor run --production

The resulting app (with Jscrambler plugin) can be found in this Github repository.

Known problems

There are no known problems integrating Jscrambler with Meteor itself. Since you can use Meteor alongside with other frameworks (such as Angular, React, Vue.js, etc.) to develop your app, some transformations might need some tweaks in order to fully comply with them. You can also check examples of other integrations.