Showing posts with label build. Show all posts
Showing posts with label build. Show all posts

Thursday, December 8, 2016

Warning: Cannot create property 'subarray' on string

For an old project, after I npm install, try to grunt to build the project, I got the following error

Running "uglify:dist" (uglify) task
File "../onFirefox-build/chrome/content/js/MX.js" created.
Warning: Cannot create property 'subarray' on string

Running "cssmin:compress" (cssmin) task
File ../onFirefox-build/chrome/content/css/global.css created.
Warning: Cannot create property 'subarray' on string

A bug may have been created in the way the grunt-contrib-uglify interacts with the underlying uglifyjs api. To resolve this issue, it is better to upgrade grunt-contrib-uglify.

Based on the guess, I updated the cssmin and uglify versions to latest in package.json, then do npm update.

After that, grunt build passed. Hooray!

Thursday, October 8, 2015

mainConfigFile in requirejs

Today I got two errors when do requirejs build.

The first error is:
[Error: Error: ENOENT, no such file or directory 'undefinedjquery.js'
    at Error (native)
]

Googled a while and realized I do something like below in main.js while I use mainConfigFile in Gruntfile.js
var options = {}
require.config(options)
The second error is:
[Error: Error: The config in mainConfigFile /Users/jimz/Workshop/boardUI/trunk/moxtra/site/scripts/app/main.js cannot be used because it cannot be evaluated correctly while running in the optimizer. Try only using a config that is also valid JSON, or do not use mainConfigFile and instead copy the config values needed into a build file or command line arguments given to the optimizer.

Source error from parsing: /Users/jimz/Workshop/boardUI/trunk/moxtra/site/scripts/app/main.js: ReferenceError: navigator is not defined

This error is more self-descriptive and it means build environment is different from browser context, so navigator is not defined.

From above 2 errors, we should understand two facts about mainConfigFile option. It is used in build environment instead of browser env, so most JavaScript functions will not work. Let's take further study about this.

Sometimes we want to avoid duplicate path/shim mapping using main.js file as configuration file in requirejs through mainConfigFile setting in requirejs build file. The documentation describes as below to clarify this option.

https://github.com/jrburke/r.js/blob/master/build/example.build.js#L27
//By default all the configuration for optimization happens from the command
//line or by properties in the config file, and configuration that was
//passed to requirejs as part of the app's runtime "main" JS file is *not*
//considered. However, if you prefer the "main" JS file configuration
//to be read for the build so that you do not have to duplicate the values
//in a separate configuration, set this property to the location of that
//main JS file. The first requirejs({}), require({}), requirejs.config({}),
//or require.config({}) call found in that file will be used.
//As of 2.1.10, mainConfigFile can be an array of values, with the last
//value's config take precedence over previous values in the array.
mainConfigFile: '../some/path/to/main.js',

https://github.com/jrburke/r.js/issues/270
It is probably referencing variables that do not work when evaluated outside of a browser context. For instance if you do something like this, it will not work:
requirejs.config({
  baseUrl: location.href
});
Since location is not available in the build environment. Same thing if you use functions to set up part of the config.

You could try leaving out the baseUrl in a first require.config() call in the mainConfigFile, as I believe right now the optimizer will only read the first one. Then do a require.config({ baseUrl: ''}) call after that first config call. So, just two config calls in a row. The config values are merged by requirejs.

The typical configuration in main.js looks like below, first config is static, second config is using dynamic with variables and javascript.
require.config({
  paths: { /*snip*/ },
  shim: { /*snip*/ }
});
require.config({
  baseUrl: $app.configuration.mediaDomain + 'scripts/',
  urlArgs: 'c=' + $app.configuration.version
});

Tuesday, October 16, 2012

First build using grunt.js

Gruntjs is so cool, I should try out this excellent Javscript build tool earlier. It has built-in task, APIs, and pluginable framework (see http://gruntjs.com/ for various plugins). Base off node, gruntjs tries to meet extensive Javascript project build requirements. For details, check out https://github.com/gruntjs. This note describes the steps to create grunt.js build script for one of my Javascript projects.

Precondition:

Node and NPM are installed. Verify its installation and version, refer to below commands

node --version
v0.8.7

npm --version
1.1.49

Purpose:

Minify JS
Minify CSS
Optimize images
Compress HTML
Package build

Steps:

Install grunt globally: 
sudo npm install -g grunt

Install plugins locally:
sudo npm install grunt-smushit (to smush images)
sudo npm install grunt-contrib-copy (to copy files/folder)
sudo npm install grunt-contrib-mincss (to minify CSS files)
sudo npm install grunt-htmlcompressor (to compress HTML)
sudo npm install grunt-contrib-clean (to clean up build target)

grunt built-in task "min" is to minify JS using UglifyJS

Generate project scaffolding
grunt init:gruntfile

Create grunt.js to build project