diff --git a/plugin.js b/plugin.js index a9b48fe..0632226 100644 --- a/plugin.js +++ b/plugin.js @@ -18,6 +18,7 @@ var parseOpts = { var runtimePath = require.resolve('./browser') // Used to tag nodes that are splitRequire() calls. var kIsSplitRequireCall = Symbol('is split-require call') +var kIsBoundSrCall = Symbol('is bound split-require call') function mayContainSplitRequire (str) { return str.includes('split-require') @@ -49,6 +50,13 @@ function createSplitRequireDetector () { if (node.type === 'CallExpression' && node.callee.type === 'Identifier' && check(node.callee.name)) { node[kIsSplitRequireCall] = true } + // var sr = require('split-require'); var load = sr.bind(null, './xyz') + if (node.type === 'CallExpression' && + node.callee.type === 'MemberExpression' && + node.callee.object.type === 'Identifier' && check(node.callee.object.name) && + node.callee.property.type === 'Identifier' && node.callee.property.name === 'bind') { + node[kIsBoundSrCall] = true + } return false } @@ -84,6 +92,11 @@ function transformSplitRequireCalls (file, opts) { arg.edit.prepend('require(').append(')') hasSplitRequireCall = true } + if (node[kIsBoundSrCall]) { + var arg = node.arguments[1] // eslint-disable-line no-redeclare + arg.edit.prepend('require(').append(')') + hasSplitRequireCall = true + } }) // Pass through unchanged. @@ -143,6 +156,9 @@ function createSplitter (b, opts) { if (node[kIsSplitRequireCall]) { processSplitRequire(row, node) } + if (node[kIsBoundSrCall]) { + processBoundSplitRequire(row, node) + } }) row.transformable = result @@ -196,10 +212,13 @@ function createSplitter (b, opts) { if (mainRows.includes(depEntry.id)) { // this entry point is also non-dynamically required by the main bundle. // we should not move it into a dynamic bundle. - node.callee.edit.append('.t') - // wrap this in a closure so we call `require()` asynchronously, - // just like if it was actually dynamically loaded - node.arguments[0].edit.prepend('function(){return require(').append(')}') + if (node[kIsBoundSrCall]) { + node.callee.object.edit.append('.t') + node.arguments[1].edit.prepend('function(){return require(').append(')}') + } else { + node.callee.edit.append('.t') + node.arguments[0].edit.prepend('function(){return require(').append(')}') + } // add the dependency back row.deps[depEntry.id] = depEntry.id @@ -337,6 +356,18 @@ function createSplitter (b, opts) { queueSplitRequire(row.id, resolved, node) } + function processBoundSplitRequire (row, node) { + var requirePath = node.arguments[1].arguments[0].value + var resolved = row.deps[requirePath] + if (resolved == null) { + resolved = requirePath + } + + node.arguments[1].edit.update(JSON.stringify(resolved)) + + queueSplitRequire(row.id, resolved, node) + } + function getRow (id) { return rowsById[id] } diff --git a/test/bound/app.js b/test/bound/app.js new file mode 100644 index 0000000..9b3c8e2 --- /dev/null +++ b/test/bound/app.js @@ -0,0 +1,8 @@ +var sr = require('split-require') + +var load1 = sr.bind(null, './one') +var load2 = sr.bind(null, './two') + +load1(function () { + load2(function () {}) +}) diff --git a/test/bound/expected/bundle.2.js b/test/bound/expected/bundle.2.js new file mode 100644 index 0000000..d6dcbcb --- /dev/null +++ b/test/bound/expected/bundle.2.js @@ -0,0 +1,6 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o element for this bundle was already added. + if (prev) return + + var s = document.createElement('script') + s.async = true + s.type = 'application/javascript' + s.src = url + s.onerror = function () { + onload(Error('Failed to load')) + } + document.body.appendChild(s) +} + +// Called by dynamic bundles once they have loaded. +function loadedBundle (index, result) { + if (receivers[index]) { + receivers[index](null, result) + } else { + cache[index] = result + } +} + +// "Load" a module that we know is included in this bundle. +var nextTick = window.setImmediate || window.setTimeout +function loadLocal (requirer, onload) { + nextTick(function () { + // Just execute the module if no callback is provided + if (!onload) return requirer() + try { + onload(null, requirer()) + } catch (err) { + onload(err) + } + }) +} + +// Map dynamic bundle entry point IDs to URLs. +load.b = {} + +// Used by the bundle. +load.l = loadedBundle +load.t = loadLocal + +module.exports = load + +},{}]},{},["split_require_mappings",1]); diff --git a/test/bound/one.js b/test/bound/one.js new file mode 100644 index 0000000..f0fe904 --- /dev/null +++ b/test/bound/one.js @@ -0,0 +1 @@ +module.exports = 'one' diff --git a/test/bound/two.js b/test/bound/two.js new file mode 100644 index 0000000..53ab00d --- /dev/null +++ b/test/bound/two.js @@ -0,0 +1 @@ +module.exports = 'two'