Loading presentation...

Present Remotely

Send the link below via email or IM

Copy

Present to your audience

Start remote presentation

  • Invited audience members will follow you as you navigate and present
  • People invited to a presentation do not need a Prezi account
  • This link expires 10 minutes after you close the presentation
  • A maximum of 30 users can follow your presentation
  • Learn more about this feature in our knowledge base article

Do you really want to delete this prezi?

Neither you, nor the coeditors you shared it with will be able to recover it again.

DeleteCancel

Make your likes visible on Facebook?

Connect your Facebook account to Prezi and let your likes appear on your timeline.
You can change this under Settings & Account at any time.

No, thanks

RequireJS In Chrome Extensions

No description
by

Daniel Prentis

on 14 January 2013

Comments (0)

Please log in to add your comment.

Report abuse

Transcript of RequireJS In Chrome Extensions

RequireJS In A Chrome Extension?! The How And Why JavaScript file and module loader
uses AMD (Asynchronous Module Definition)
asynchronous module loading is well suited to browser environments What is RequireJS? CommonJS module:
var dep1 = require('dependency1');
var dep2 = require('dependency2');
/* do something here with deps...*/
exports.result = myResult; AMD vs CommonJS it works (by injecting script tags into the html document)
due to manifest v 2.0 limitations (banning eval in the background script) there aren't many other options right now Why in Chrome Extensions? we want the same module mechanism to be used extension-wide
we want a single module definition to be usable anywhere in the extension (provided it doesn't access the background-only chrome API)
we want to be able to unit-test the modules
we want as little repeated code as possible The Goal Extension Folder
/html - contains any html files used by extension (background.html, popup.html)
/js - contains all extension JavaScript code. In the root are main js files: background.js, content.js, popup.js and RequireJS specific files.
/lib - external libraries
/modules - all extension-specific code in AMD modules
/typeA - One type of module.
/typeB - Another type of module.
/test - contains all test suite Javascript code for Jasmine-node.
/specs - unit test modules
/modules - unit test-specific utility and RequireJS configuration modules The Setup js/modules/typeB/myBaseModule.js:
define({
color: 'blue'
}); Some (Unuseful) Modules manifest.json (relevant parts):
...
"background": {
"page": "html/background.html"
},
... The Background Script manifest.json (relevant parts):
...
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": [
"js/lib/require.js",
"js/requireContent.js",
"js/requireConfig.js",
"js/content.js"
]
}
],
...
"web_accessible_resources": [
"js/modules/*",
"js/lib/*"
]
... The Content Script run-tests.sh:
#!/bin/bash
# if node modules are not installed, install them..
if [ ! -d "node_modules" ]
then
echo "Installing dependencies.."
npm install
fi
# run tests
echo "Starting test execution:"
echo ""
jasmine-node --verbose test/specs Unit Tests
RequireJS module:
define(['dependency1', 'dependency2'],
function(dep1, dep2) {
/* do something here with deps...*/
return { result: myResult };
}); AMD dependencies are specified up-front in array. This allows the AMD loader to more easily optimize loading and execution of modules in the browser environment. html/background.html:
<!doctype html>
<html>
<head>
<script src="../js/lib/require.js"></script>
<script src="../js/requireConfig.js"></script>
<script src="../js/lib/jquery.js"></script>
<!-- script tags for named AMD or non-AMD libraries here -->
<script src="../js/background.js"></script>
</head>
<body>
</body>
</html> js/background.js:
requirejs.config(requirejsConfig);

requirejs(['jquery', 'typeA/myModule'],
function($, myModule) {
console.log('My favourite color: ' + myModule.color);
console.log('My second favourite color: ' + myModule.baseColor);
}); js/requireConfig.js:
var requirejsConfig = {
// by default load any module IDs from js/modules
baseUrl: '/js/modules',
// optionally specify different paths for specific modules
paths: {
lib: '/js/lib'
}
}; js/content.js:
requirejs.config(requirejsConfig);

requirejs(['jquery', 'typeA/myModule'],
function($, myModule) {
console.log('My favourite color: ' + myModule.color);
console.log('My second favourite color: ' + myModule.baseColor);
}); js/requireContent.js:
require.load = function (context, moduleName, url) {
var xhr;
xhr = new XMLHttpRequest();
xhr.open("GET", chrome.extension.getURL(url) + '?r=' + (new Date()).getTime(), true);
xhr.onreadystatechange = function (e) {
if (xhr.readyState === 4 && xhr.status === 200) {
eval(xhr.responseText);
context.completeLoad(moduleName)
}
};
xhr.send(null);
}; test/specs/myModule.spec.js:
// initialize RequireJS
var requirejs = require('requirejs');
var rc = require('../modules/requireConfig');
requirejs.config(rc.init());

// run unit test with dependencies
var myModule = requirejs('typeA/myModule');

describe("Sample unit test", function() {
it ("myModule.color should equal 'red' and baseColor should equal 'blue'",
function() {
expect(myModule.color).toEqual('red');
expect(myModule.myBaseColor).toEqual('blue');
});
}); test/modules/requireConfig.js:
// RequireJS configuration module
// Takes configuration from project and modifies it for use with unit tests
;(function() {
var fs = require('fs');
exports.init = function() {
// synchronously read script file containing requirejsConfig
try {
var data = fs.readFileSync('js/requireConfig.js', 'ascii');
}
catch(e) {
console.error(e);
return {};
}

// evaluate script to initialise requirejsConfig object
eval(data.toString());

// absolute path prefix for test suite
var pathPrefix = __dirname + '/../..';

// now we modify the config
var rc = requirejsConfig;

// modify the baseUrl to point to our modules
rc.baseUrl = pathPrefix + rc.baseUrl;

// modify any path urls
var path;
for (path in rc.paths) {
if (typeof rc.paths[path] === 'string') {
rc.paths[path] = pathPrefix + rc.paths[path];
}
}

// optionally do other clever things to the config..

return rc;
};
}).call(this); package.json:
{
"name": "Test",
"version": "0.0.1",
"devDependencies": {
"requirejs" : ">= 2.0.4"
}
} RequireJS can be used in a Chrome Extension and works well, although the setup can be a bit finicky... Conclusion js/modules/typeA/myModule.js:
define(['typeB/myBaseModule'],
function(myBaseModule) {
return {
color: 'red',
baseColor: myBaseModule.color
};
}); Any questions?
Full transcript