Last active
February 5, 2016 15:55
-
-
Save nickjacob/5dbe83cc1365a85190a2 to your computer and use it in GitHub Desktop.
Revisions
-
Nick Jacob revised this gist
Feb 5, 2016 . 1 changed file with 18 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,8 +1,12 @@ # Inlining Bidder SDKs in Prebid To improve performance in Prebid (or any other header bidding setup), you can inline third-party SDKs/resources that are required to make bids. This removes network requests/roundtrips which can have a significant impact (especially on mobile) — cutting down time to first bid request. One way to inline the scripts as part of your build process is to replace calls to `adloader.loadScript` with a preprocessor directive that downloads the script and inlines its contents into the page. See below for instructions, with AOL/ADTECH as an example. ## `gulp-preprocess` & `request` Add [gulp-preprocess](https://github.com/jas/gulp-preprocess) & [request](https://github.com/request/request): `npm install --save-dev gulp-preprocess request`, this will let you add preprocessing directives to the code, and add the `request` library to make HTTP requests. @@ -15,7 +19,6 @@ function preprocessFilter() { context: { scripts: { adtech: ['http://aka-cdn.adtechus.com/dt/common/DAC.js'], yieldbot: 'http://cdn.yldbt.com/js/yieldbot.intent.js' }, script: function (args) { @@ -27,7 +30,6 @@ function preprocessFilter() { callback = args[2]; if (toString.call(src) !== '[object Array]') { src = [src]; } @@ -46,8 +48,19 @@ function preprocessFilter() { return script; }).join(';'); /** * Since this will be evaluated in an IIFE, we want to avoid situations where the script sets a global variable * implicitly (e.g., via `var globalVar = value`), by attaching that variable to the `window` object: */ var exportCheck = 'try{ if (' + exported + ' && !window.' + exported + '){window.' + exported + '='+ exported + ';} }catch(e){};'; /** * this wraps the script's contents in an IIFE that * is deferred, which should reduce the impact on frame-rate * from the browser evaluating such a large/continuous chunk of JS. * because it's asynchronous, we let the user provide a callback * which gets called when the script & its global variable are available. */ return [ "/** ", src, @@ -59,7 +72,7 @@ function preprocessFilter() { "');", exportCheck, callback + "();", "}, 1);" ].join(''); } } -
Nick Jacob created this gist
Feb 5, 2016 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,135 @@ # Inlining Bidder SDKs in Prebid ## `gulp-preprocess` Add gulp-preprocess: `npm install --save-dev gulp-preprocess request`, this will let you add preprocessing directives to the code, and add the `request` library to make HTTP requests. Then add a gulp task to preprocess the code **before** it is bundled: ```javascript function preprocessFilter() { return preprocess({ context: { scripts: { adtech: ['http://aka-cdn.adtechus.com/dt/common/DAC.js'], openx: 'http://ox-d.aplus.com/w/1.0/jstag', yieldbot: 'http://cdn.yldbt.com/js/yieldbot.intent.js' }, script: function (args) { // it's an array, so get // the first argument var src = args[0], exported = args[1], callback = args[2]; if (toString.call(src) !== '[object Array]') { console.log('src is not an array..'); src = [src]; } var scripts = src.map(function (scriptSrc) { var res = request('GET', scriptSrc, { headers: { 'User-Agent': CHROME_UA } }), script = res.getBody(); if (!script.length) { throw scriptSrc + ' returned error'; } return script; }).join(';'); var exportCheck = 'try{ if (' + exported + ' && !window.' + exported + '){window.' + exported + '='+ exported + ';} }catch(e){};'; return [ "/** ", src, " @", (new Date), " */;setTimeout(function(){", "(1,eval)('", jsStringEscape(scripts.toString()), "');", exportCheck, callback + "();", "}, 0);" ].join(''); } } }); } gulp.task('preprocess', function () { return gulp.src(['src/*.js', 'src/**/*.js', 'src/*.json']) .pipe(preprocessFilter()) .pipe(gulp.dest(buildDir)); }); ``` Change the `build-dev` task to first preprocess: ```javascript gulp.task('build-dev', ['preprocess', 'clean-dist'], function () { return gulp.src([buildDir + '/prebid.js']) .pipe(browserify({ debug: false, standalone: 'pbjs' })) .pipe(derequire()) .pipe(header(banner, { pkg: pkg })) .pipe(gulp.dest(releaseDir)); }); ``` ## Add the directive to `src/adapters/aol.js` The `@exec script()` directive works by downloading the script, putting its code into a string that will get `eval`'d, and then calling the specified function when the script is evaluated/available. For aol, we add a `_onScript` function to the adapter scope: ```javascript var _scriptLoadQueue = []; /** * When the script is available, call any waiting handlers * and then make further calls (pushes) immediate */ function _onScript() { function _call(fn){ fn(); } utils._each(_scriptLoadQueue, _call); _scriptLoadQueue.prototype.push = _call; } ``` ```javascript function _callBids(params) { bids = params.bids; if (!bids || !bids.length) return; _scriptLoadQueue.push(_reqBids); } /** * Inline the specified script (provided in the gulpfile) * @param {string} url * @param {string} varName - ensure that this variable is available on * the global scope. * @param {string} callbackName - call this function (in this scope) * when the script is ready/evaluated * @return {Function} inline eval IIFE */ /* @exec script(scripts.adtech, 'ADTECH', '_onScript') */ ```