diff --git a/cms/static/cms/js/build.js b/cms/static/cms/js/build.js
index 2112606a1c3644f429d160db34c9480e3438da42..70690676af8b56cef54b27cd6edfb1f391d155b7 100644
--- a/cms/static/cms/js/build.js
+++ b/cms/static/cms/js/build.js
@@ -26,14 +26,12 @@
             'js/factories/group_configurations',
             'js/certificates/factories/certificates_page_factory',
             'js/factories/index',
-            'js/factories/library',
             'js/factories/manage_users',
             'js/factories/outline',
             'js/factories/register',
             'js/factories/settings',
             'js/factories/settings_advanced',
             'js/factories/settings_graders',
-            'js/factories/textbooks',
             'js/factories/videos_index',
         ]),
         /**
diff --git a/cms/static/js/factories/base.js b/cms/static/js/factories/base.js
index 7f61b473c9e9f9cbf086bf21f9adc3f2257d243c..a714393573074217e98732a54da6cb829d43fe8b 100644
--- a/cms/static/js/factories/base.js
+++ b/cms/static/js/factories/base.js
@@ -1,3 +1,5 @@
+// We can't convert this to an es6 module until all factories that use it have been converted out
+// of RequireJS
 define(['js/base', 'cms/js/main', 'js/src/logger', 'datepair', 'accessibility',
     'ieshim', 'tooltip_manager', 'lang_edx', 'js/models/course'],
     function() {
diff --git a/cms/static/js/factories/container.js b/cms/static/js/factories/container.js
index 8861d6f1249a1de92ca13b1d8396c41634e5f53f..cfca298851830dd6ce5ec1ffa7ce1d63c2c6e041 100644
--- a/cms/static/js/factories/container.js
+++ b/cms/static/js/factories/container.js
@@ -1,21 +1,26 @@
-define([
-    'jquery', 'underscore', 'js/models/xblock_container_info', 'js/views/pages/container',
-    'js/collections/component_template', 'xmodule', 'cms/js/main',
-    'xblock/cms.runtime.v1'
-],
-function($, _, XBlockContainerInfo, ContainerPage, ComponentTemplates, xmoduleLoader) {
-    'use strict';
-    return function(componentTemplates, XBlockInfoJson, action, options) {
-        var main_options = {
-            el: $('#content'),
-            model: new XBlockContainerInfo(XBlockInfoJson, {parse: true}),
-            action: action,
-            templates: new ComponentTemplates(componentTemplates, {parse: true})
-        };
+import * as $ from 'jquery';
+import * as _ from 'underscore';
+import * as XBlockContainerInfo from 'js/models/xblock_container_info';
+import * as ContainerPage from 'js/views/pages/container';
+import * as ComponentTemplates from 'js/collections/component_template';
+import * as xmoduleLoader from 'xmodule';
+import './base';
+import 'cms/js/main';
+import 'xblock/cms.runtime.v1';
 
-        xmoduleLoader.done(function() {
-            var view = new ContainerPage(_.extend(main_options, options));
-            view.render();
-        });
+'use strict';
+export default function ContainerFactory(componentTemplates, XBlockInfoJson, action, options) {
+    var main_options = {
+        el: $('#content'),
+        model: new XBlockContainerInfo(XBlockInfoJson, {parse: true}),
+        action: action,
+        templates: new ComponentTemplates(componentTemplates, {parse: true})
     };
-});
+
+    xmoduleLoader.done(function() {
+        var view = new ContainerPage(_.extend(main_options, options));
+        view.render();
+    });
+};
+
+export {ContainerFactory}
diff --git a/cms/static/js/factories/context_course.js b/cms/static/js/factories/context_course.js
new file mode 100644
index 0000000000000000000000000000000000000000..475e5a6282c62f22cfb7163309c755eaff85d0a0
--- /dev/null
+++ b/cms/static/js/factories/context_course.js
@@ -0,0 +1,3 @@
+import * as ContextCourse from 'js/models/course';
+
+export {ContextCourse}
diff --git a/cms/static/js/factories/library.js b/cms/static/js/factories/library.js
index e6eb929069344af539dce5394004e56e2f6d53ff..4cde6873f939b51dc0e9a6a420793f96d7c86290 100644
--- a/cms/static/js/factories/library.js
+++ b/cms/static/js/factories/library.js
@@ -1,23 +1,28 @@
-define([
-    'jquery', 'underscore', 'js/models/xblock_info', 'js/views/pages/paged_container',
-    'js/views/library_container', 'js/collections/component_template', 'xmodule', 'cms/js/main',
-    'xblock/cms.runtime.v1'
-],
-function($, _, XBlockInfo, PagedContainerPage, LibraryContainerView, ComponentTemplates, xmoduleLoader) {
-    'use strict';
-    return function(componentTemplates, XBlockInfoJson, options) {
-        var main_options = {
-            el: $('#content'),
-            model: new XBlockInfo(XBlockInfoJson, {parse: true}),
-            templates: new ComponentTemplates(componentTemplates, {parse: true}),
-            action: 'view',
-            viewClass: LibraryContainerView,
-            canEdit: true
-        };
+import * as $ from 'jquery';
+import * as _ from 'underscore';
+import * as XBlockInfo from 'js/models/xblock_info';
+import * as PagedContainerPage from 'js/views/pages/paged_container';
+import * as LibraryContainerView from 'js/views/library_container';
+import * as ComponentTemplates from 'js/collections/component_template';
+import * as xmoduleLoader from 'xmodule';
+import 'cms/js/main';
+import 'xblock/cms.runtime.v1';
 
-        xmoduleLoader.done(function() {
-            var view = new PagedContainerPage(_.extend(main_options, options));
-            view.render();
-        });
+'use strict';
+export default function LibraryFactory(componentTemplates, XBlockInfoJson, options) {
+    var main_options = {
+        el: $('#content'),
+        model: new XBlockInfo(XBlockInfoJson, {parse: true}),
+        templates: new ComponentTemplates(componentTemplates, {parse: true}),
+        action: 'view',
+        viewClass: LibraryContainerView,
+        canEdit: true
     };
-});
+
+    xmoduleLoader.done(function() {
+        var view = new PagedContainerPage(_.extend(main_options, options));
+        view.render();
+    });
+};
+
+export {LibraryFactory}
diff --git a/cms/static/js/factories/login.js b/cms/static/js/factories/login.js
index fdbcef31e8ec05ec716f068fd98e0fe07c248ab9..fa8bb454a9a22c06bfdd4b54dfff6bf4bfe6a259 100644
--- a/cms/static/js/factories/login.js
+++ b/cms/static/js/factories/login.js
@@ -1,57 +1,62 @@
-define(['jquery.cookie', 'utility', 'common/js/components/utils/view_utils'], function(cookie, utility, ViewUtils) {
-    'use strict';
-    return function LoginFactory(homepageURL) {
-        function postJSON(url, data, callback) {
-            $.ajax({
-                type: 'POST',
-                url: url,
-                dataType: 'json',
-                data: data,
-                success: callback
-            });
-        }
+import * as cookie from 'jquery.cookie';
+import * as utility from 'utility';
+import * as ViewUtils from 'common/js/components/utils/view_utils';
 
-        // Clear the login error message when credentials are edited
-        $('input#email').on('input', function() {
-            $('#login_error').removeClass('is-shown');
-        });
+'use strict';
 
-        $('input#password').on('input', function() {
-            $('#login_error').removeClass('is-shown');
+export default function LoginFactory(homepageURL) {
+    function postJSON(url, data, callback) {
+        $.ajax({
+            type: 'POST',
+            url: url,
+            dataType: 'json',
+            data: data,
+            success: callback
         });
+    }
+
+    // Clear the login error message when credentials are edited
+    $('input#email').on('input', function() {
+        $('#login_error').removeClass('is-shown');
+    });
 
-        $('form#login_form').submit(function(event) {
-            event.preventDefault();
-            var $submitButton = $('#submit'),
-                deferred = new $.Deferred(),
-                promise = deferred.promise();
-            ViewUtils.disableElementWhileRunning($submitButton, function() { return promise; });
-            var submit_data = $('#login_form').serialize();
+    $('input#password').on('input', function() {
+        $('#login_error').removeClass('is-shown');
+    });
 
-            postJSON('/login_post', submit_data, function(json) {
-                if (json.success) {
-                    var next = /next=([^&]*)/g.exec(decodeURIComponent(window.location.search));
-                    if (next && next.length > 1 && !isExternal(next[1])) {
-                        ViewUtils.redirect(next[1]);
-                    } else {
-                        ViewUtils.redirect(homepageURL);
-                    }
-                } else if ($('#login_error').length === 0) {
-                    $('#login_form').prepend(
-                        '<div id="login_error" class="message message-status error">' +
-                        json.value +
-                        '</span></div>'
-                    );
-                    $('#login_error').addClass('is-shown');
-                    deferred.resolve();
+    $('form#login_form').submit(function(event) {
+        event.preventDefault();
+        var $submitButton = $('#submit'),
+            deferred = new $.Deferred(),
+            promise = deferred.promise();
+        ViewUtils.disableElementWhileRunning($submitButton, function() { return promise; });
+        var submit_data = $('#login_form').serialize();
+
+        postJSON('/login_post', submit_data, function(json) {
+            if (json.success) {
+                var next = /next=([^&]*)/g.exec(decodeURIComponent(window.location.search));
+                if (next && next.length > 1 && !isExternal(next[1])) {
+                    ViewUtils.redirect(next[1]);
                 } else {
-                    $('#login_error')
-                        .stop()
-                        .addClass('is-shown')
-                        .html(json.value);
-                    deferred.resolve();
+                    ViewUtils.redirect(homepageURL);
                 }
-            });
+            } else if ($('#login_error').length === 0) {
+                $('#login_form').prepend(
+                    '<div id="login_error" class="message message-status error">' +
+                    json.value +
+                    '</span></div>'
+                );
+                $('#login_error').addClass('is-shown');
+                deferred.resolve();
+            } else {
+                $('#login_error')
+                    .stop()
+                    .addClass('is-shown')
+                    .html(json.value);
+                deferred.resolve();
+            }
         });
-    };
-});
+    });
+};
+
+export {LoginFactory}
diff --git a/cms/static/js/factories/textbooks.js b/cms/static/js/factories/textbooks.js
index 0641e025d36a0465ea72509d0d144674552d9bbb..2fd11e407f182e673957b3b2f4046d0ed2aec582 100644
--- a/cms/static/js/factories/textbooks.js
+++ b/cms/static/js/factories/textbooks.js
@@ -1,20 +1,23 @@
-define([
-    'gettext', 'js/models/section', 'js/collections/textbook', 'js/views/list_textbooks'
-], function(gettext, Section, TextbookCollection, ListTextbooksView) {
-    'use strict';
-    return function(textbooksJson) {
-        var textbooks = new TextbookCollection(textbooksJson, {parse: true}),
-            tbView = new ListTextbooksView({collection: textbooks});
+import * as gettext from 'gettext';
+import * as Section from 'js/models/section';
+import * as TextbookCollection from 'js/collections/textbook';
+import * as ListTextbooksView from 'js/views/list_textbooks';
 
-        $('.content-primary').append(tbView.render().el);
-        $('.nav-actions .new-button').click(function(event) {
-            tbView.addOne(event);
-        });
-        $(window).on('beforeunload', function() {
-            var dirty = textbooks.find(function(textbook) { return textbook.isDirty(); });
-            if (dirty) {
-                return gettext('You have unsaved changes. Do you really want to leave this page?');
-            }
-        });
-    };
-});
+'use strict';
+export default function TextbooksFactory(textbooksJson) {
+    var textbooks = new TextbookCollection(textbooksJson, {parse: true}),
+        tbView = new ListTextbooksView({collection: textbooks});
+
+    $('.content-primary').append(tbView.render().el);
+    $('.nav-actions .new-button').click(function(event) {
+        tbView.addOne(event);
+    });
+    $(window).on('beforeunload', function() {
+        var dirty = textbooks.find(function(textbook) { return textbook.isDirty(); });
+        if (dirty) {
+            return gettext('You have unsaved changes. Do you really want to leave this page?');
+        }
+    });
+};
+
+export {TextbooksFactory}
diff --git a/cms/static/js/factories/xblock_validation.js b/cms/static/js/factories/xblock_validation.js
index 4bcfc3b339174dcedc3130652745c04290e46969..56786c89d9c1d9270a10e242a27689aed19ef494 100644
--- a/cms/static/js/factories/xblock_validation.js
+++ b/cms/static/js/factories/xblock_validation.js
@@ -1,19 +1,22 @@
-define(['js/views/xblock_validation', 'js/models/xblock_validation'],
-function(XBlockValidationView, XBlockValidationModel) {
-    'use strict';
-    return function(validationMessages, hasEditingUrl, isRoot, isUnit, validationEle) {
-        var model, response;
 
-        if (hasEditingUrl && !isRoot) {
-            validationMessages.showSummaryOnly = true;
-        }
-        response = validationMessages;
-        response.isUnit = isUnit;
+import * as XBlockValidationView from 'js/views/xblock_validation';
+import * as XBlockValidationModel from 'js/models/xblock_validation';
 
-        model = new XBlockValidationModel(response, {parse: true});
+'use strict';
+export default function XBlockValidationFactory(validationMessages, hasEditingUrl, isRoot, isUnit, validationEle) {
+    var model, response;
 
-        if (!model.get('empty')) {
-            new XBlockValidationView({el: validationEle, model: model, root: isRoot}).render();
-        }
-    };
-});
+    if (hasEditingUrl && !isRoot) {
+        validationMessages.showSummaryOnly = true;
+    }
+    response = validationMessages;
+    response.isUnit = isUnit;
+
+    model = new XBlockValidationModel(response, {parse: true});
+
+    if (!model.get('empty')) {
+        new XBlockValidationView({el: validationEle, model: model, root: isRoot}).render();
+    }
+};
+
+export {XBlockValidationFactory}
diff --git a/cms/static/js/pages/container.js b/cms/static/js/pages/container.js
deleted file mode 100644
index 79937020db63556b5345b0b9391d4a114fc7c89a..0000000000000000000000000000000000000000
--- a/cms/static/js/pages/container.js
+++ /dev/null
@@ -1,8 +0,0 @@
-define(
-    ['js/factories/container', 'common/js/utils/page_factory', 'js/factories/base', 'js/pages/course'],
-    function(ContainerFactory, invokePageFactory) {
-        'use strict';
-        invokePageFactory('ContainerFactory', ContainerFactory);
-    }
-);
-
diff --git a/cms/static/js/pages/course.js b/cms/static/js/pages/course.js
deleted file mode 100644
index 5334fedbdec6da00df3a253096475901145b73a6..0000000000000000000000000000000000000000
--- a/cms/static/js/pages/course.js
+++ /dev/null
@@ -1,8 +0,0 @@
-define(
-    ['js/models/course'],
-    function(ContextCourse) {
-        'use strict';
-        window.course = new ContextCourse(window.pageFactoryArguments.ContextCourse[0]);
-    }
-);
-
diff --git a/cms/static/js/pages/library.js b/cms/static/js/pages/library.js
deleted file mode 100644
index 846ba7b11120fe61d28c42e044fd6acd755d111d..0000000000000000000000000000000000000000
--- a/cms/static/js/pages/library.js
+++ /dev/null
@@ -1,8 +0,0 @@
-define(
-    ['js/factories/library', 'common/js/utils/page_factory', 'js/factories/base'],
-    function(LibraryFactory, invokePageFactory) {
-        'use strict';
-        invokePageFactory('LibraryFactory', LibraryFactory);
-    }
-);
-
diff --git a/cms/static/js/pages/login.js b/cms/static/js/pages/login.js
deleted file mode 100644
index 449a1190f6418ef06ffb54ad41411082d588d8df..0000000000000000000000000000000000000000
--- a/cms/static/js/pages/login.js
+++ /dev/null
@@ -1,8 +0,0 @@
-define(
-    ['js/factories/login', 'common/js/utils/page_factory', 'js/factories/base'],
-    function(LoginFactory, invokePageFactory) {
-        'use strict';
-        invokePageFactory('LoginFactory', LoginFactory);
-    }
-);
-
diff --git a/cms/static/js/pages/textbooks.js b/cms/static/js/pages/textbooks.js
deleted file mode 100644
index 7d524fbd2909b2f9889bc901dc8c5f92050a86c2..0000000000000000000000000000000000000000
--- a/cms/static/js/pages/textbooks.js
+++ /dev/null
@@ -1,7 +0,0 @@
-define(
-    ['js/factories/textbooks', 'common/js/utils/page_factory', 'js/factories/base', 'js/pages/course'],
-    function(TextbooksFactory, invokePageFactory) {
-        'use strict';
-        invokePageFactory('TextbooksFactory', TextbooksFactory);
-    }
-);
diff --git a/cms/static/js/pages/xblock_validation.js b/cms/static/js/pages/xblock_validation.js
deleted file mode 100644
index b0a4cb7a7cdc0363867d91b8991de9b0414dc635..0000000000000000000000000000000000000000
--- a/cms/static/js/pages/xblock_validation.js
+++ /dev/null
@@ -1,8 +0,0 @@
-define(
-    ['js/factories/xblock_validation', 'common/js/utils/page_factory'],
-    function(XBlockValidationFactory, invokePageFactory) {
-        'use strict';
-        invokePageFactory('XBlockValidationFactory', XBlockValidationFactory);
-    }
-);
-
diff --git a/cms/static/js/sock.js b/cms/static/js/sock.js
index 44653981ff6470e486a08e947442cb3e343069d4..a68bb55bcc4122981c98fa2bbf29fc9fff2e91fe 100644
--- a/cms/static/js/sock.js
+++ b/cms/static/js/sock.js
@@ -1,39 +1,39 @@
-define(['domReady', 'jquery', 'jquery.smoothScroll'],
-    function(domReady, $) {
-        'use strict';
+import * as domReady from 'domReady';
+import * as $ from 'jquery';
+import 'jquery.smoothScroll';
 
-        var toggleSock = function(e) {
-            e.preventDefault();
+'use strict';
 
-            var $btnShowSockLabel = $(this).find('.copy-show');
-            var $btnHideSockLabel = $(this).find('.copy-hide');
-            var $sock = $('.wrapper-sock');
-            var $sockContent = $sock.find('.wrapper-inner');
+var toggleSock = function(e) {
+    e.preventDefault();
 
-            if ($sock.hasClass('is-shown')) {
-                $sock.removeClass('is-shown');
-                $sockContent.hide('fast');
-                $btnHideSockLabel.removeClass('is-shown').addClass('is-hidden');
-                $btnShowSockLabel.removeClass('is-hidden').addClass('is-shown');
-            } else {
-                $sock.addClass('is-shown');
-                $sockContent.show('fast');
-                $btnHideSockLabel.removeClass('is-hidden').addClass('is-shown');
-                $btnShowSockLabel.removeClass('is-shown').addClass('is-hidden');
-            }
+    var $btnShowSockLabel = $(this).find('.copy-show');
+    var $btnHideSockLabel = $(this).find('.copy-hide');
+    var $sock = $('.wrapper-sock');
+    var $sockContent = $sock.find('.wrapper-inner');
 
-            $.smoothScroll({
-                offset: -200,
-                easing: 'swing',
-                speed: 1000,
-                scrollElement: null,
-                scrollTarget: $sock
-            });
-        };
-
-        domReady(function() {
-            // toggling footer additional support
-            $('.cta-show-sock').bind('click', toggleSock);
-        });
+    if ($sock.hasClass('is-shown')) {
+        $sock.removeClass('is-shown');
+        $sockContent.hide('fast');
+        $btnHideSockLabel.removeClass('is-shown').addClass('is-hidden');
+        $btnShowSockLabel.removeClass('is-hidden').addClass('is-shown');
+    } else {
+        $sock.addClass('is-shown');
+        $sockContent.show('fast');
+        $btnHideSockLabel.removeClass('is-hidden').addClass('is-shown');
+        $btnShowSockLabel.removeClass('is-shown').addClass('is-hidden');
     }
-);
+
+    $.smoothScroll({
+        offset: -200,
+        easing: 'swing',
+        speed: 1000,
+        scrollElement: null,
+        scrollTarget: $sock
+    });
+};
+
+domReady(function() {
+    // toggling footer additional support
+    $('.cta-show-sock').bind('click', toggleSock);
+});
diff --git a/cms/templates/base.html b/cms/templates/base.html
index 0a6b896f473f53584ca26d49a996e87d5b5c83b8..ccf1a535955599314e5478b02f815b5aec10c52f 100644
--- a/cms/templates/base.html
+++ b/cms/templates/base.html
@@ -125,12 +125,9 @@ from openedx.core.release import RELEASE_LINE
     <%block name="jsextra"></%block>
 
     % if context_course:
+      <%static:webpack entry="js/factories/context_course"/>
       <script type="text/javascript">
-        if (typeof window.pageFactoryArguments == "undefined") {
-            window.pageFactoryArguments = {};
-        }
-
-        window.pageFactoryArguments['ContextCourse'] = {
+        window.course = new ContextCourse({
           id: "${context_course.id | n, js_escaped_string}",
           name: "${context_course.display_name_with_default | n, js_escaped_string}",
           url_name: "${context_course.location.block_id | n, js_escaped_string}",
@@ -139,21 +136,16 @@ from openedx.core.release import RELEASE_LINE
           display_course_number: "${context_course.display_coursenumber | n, js_escaped_string}",
           revision: "${context_course.location.branch | n, js_escaped_string}",
           self_paced: ${ context_course.self_paced | n, dump_js_escaped_json }
-        }
+        });
       </script>
     % endif
     % if user.is_authenticated:
-      <%static:invoke_page_bundle page_name='js/sock'/>
+      <%static:webpack entry='js/sock'/>
     % endif
     <%block name='page_bundle'>
       <script type="text/javascript">
       require(['js/factories/base'], function () {
-          require(['js/models/course'], function(Course) {
-              % if context_course:
-                  window.course = new Course(window.pageFactoryArguments['ContextCourse']);
-              % endif
-              <%block name='requirejs'></%block>
-          });
+        <%block name='requirejs'></%block>
       });
       </script>
     </%block>
diff --git a/cms/templates/login.html b/cms/templates/login.html
index c4966f8b669de94c8f09bf35a242f72a906c08a6..5386d96c51855a46fde6a428490b08e8101f7c7e 100644
--- a/cms/templates/login.html
+++ b/cms/templates/login.html
@@ -55,7 +55,7 @@ from openedx.core.djangolib.js_utils import js_escaped_string
 </%block>
 
 <%block name="page_bundle">
-  <%static:invoke_page_bundle page_name="js/pages/login" class_name="LoginFactory">
-    "${reverse('homepage') | n, js_escaped_string}"
-  </%static:invoke_page_bundle>
+  <%static:webpack entry="js/factories/login">
+    LoginFactory("${reverse('homepage') | n, js_escaped_string}");
+  </%static:webpack>
 </%block>
diff --git a/cms/templates/studio_xblock_wrapper.html b/cms/templates/studio_xblock_wrapper.html
index f4a2e45ac9843011cf0804eb4bb8115fd8e45910..d6e568a849e7d939786d0da119445e78e2c56e1b 100644
--- a/cms/templates/studio_xblock_wrapper.html
+++ b/cms/templates/studio_xblock_wrapper.html
@@ -27,12 +27,14 @@ block_is_unit = is_unit(xblock)
 </script>
 </%block>
 
-<%static:webpack page_name="js/pages/xblock_validation" class_name="XBlockValidationFactory">
-    ${messages | n, dump_js_escaped_json},
-    ${bool(xblock_url) | n, dump_js_escaped_json},  // xblock_url will be None or a string
-    ${bool(is_root) | n, dump_js_escaped_json},  // is_root will be None or a boolean
-    ${bool(block_is_unit) | n, dump_js_escaped_json},  // block_is_unit will be None or a boolean
-    $('div.xblock-validation-messages[data-locator="${xblock.location | n, js_escaped_string}"]')
+<%static:webpack entry="js/factories/xblock_validation">
+    XBlockValidationFactory(
+        ${messages | n, dump_js_escaped_json},
+        ${bool(xblock_url) | n, dump_js_escaped_json},  // xblock_url will be None or a string
+        ${bool(is_root) | n, dump_js_escaped_json},  // is_root will be None or a boolean
+        ${bool(block_is_unit) | n, dump_js_escaped_json},  // block_is_unit will be None or a boolean
+        $('div.xblock-validation-messages[data-locator="${xblock.location | n, js_escaped_string}"]')
+    );
 </%static:webpack>
 
 % if isinstance(xblock, (XModule, XModuleDescriptor)):
diff --git a/cms/templates/textbooks.html b/cms/templates/textbooks.html
index 49184248aa10ea0c81ca7d1570fd55308ee86f35..2a5c95522403b271f8ea542b3f611b5ba6c8b595 100644
--- a/cms/templates/textbooks.html
+++ b/cms/templates/textbooks.html
@@ -28,9 +28,9 @@ CMS.URL.LMS_BASE = "${settings.LMS_BASE}"
 </%block>
 
 <%block name="page_bundle">
-  <%static:invoke_page_bundle page_name="js/pages/textbooks" class_name="TextbooksFactory">
-     ${textbooks | n, dump_js_escaped_json}
-  </%static:invoke_page_bundle>
+  <%static:webpack entry="js/factories/textbooks">
+    TextbooksFactory(${textbooks | n, dump_js_escaped_json});
+  </%static:webpack>
 </%block>
 
 <%block name="content">
diff --git a/common/djangoapps/pipeline_mako/templates/static_content.html b/common/djangoapps/pipeline_mako/templates/static_content.html
index 91eba8da71420d2dd7a4437c78b21b66ce0070a7..56461ed7c8b54fedfd54821f7420494e0a5fc9ff 100644
--- a/common/djangoapps/pipeline_mako/templates/static_content.html
+++ b/common/djangoapps/pipeline_mako/templates/static_content.html
@@ -164,31 +164,6 @@ source, template_path = Loader(engine).load_template_source(path)
     </script>
 </%def>
 
-<%def name="invoke_page_bundle(page_name, class_name=None)">
-    <%doc>
-      Loads Javascript onto your page synchronously.
-      Uses RequireJS in development and a plain script tag in production.
-      The body of the tag should be a comma-separated list of arguments
-      to be passed to the page factory specified by the class_name argument.
-    </%doc>
-    <%
-        body = capture(caller.body)
-    %>
-    % if class_name:
-        <script type="text/javascript">
-            if (typeof pageFactoryArguments == "undefined") {
-                var pageFactoryArguments = {};
-            }
-            % if body:
-                pageFactoryArguments['${class_name | n, js_escaped_string}'] = [${ body | n, decode.utf8 }];
-            % else:
-                pageFactoryArguments['${class_name | n, js_escaped_string}'] = [];
-            % endif
-        </script>
-    % endif
-    <%self:webpack entry="${page_name}"/>
-</%def>
-
 <%def name="require_module(module_name, class_name)">
     <%doc>
       Loads Javascript onto your page synchronously.
diff --git a/common/djangoapps/terrain/ui_helpers.py b/common/djangoapps/terrain/ui_helpers.py
index 2b92fbd00d3319edba88ea60aa2b7d2dc729e8ef..b43b4855029c2094ead6a0a5815d000ac7112faa 100644
--- a/common/djangoapps/terrain/ui_helpers.py
+++ b/common/djangoapps/terrain/ui_helpers.py
@@ -48,7 +48,7 @@ REQUIREJS_WAIT = {
 
     # Dashboard
     re.compile(r'^Studio Home \|'): [
-        "js/sock", "gettext", "js/base",
+        "gettext", "js/base",
         "jquery.ui", "cms/js/main", "underscore"],
 
     # Pages
@@ -66,12 +66,10 @@ def wait(seconds):
 
 @world.absorb
 def wait_for_js_to_load():
-    requirements = None
     for test, req in REQUIREJS_WAIT.items():
         if test.search(world.browser.title):
-            requirements = req
+            world.wait_for_requirejs(req)
             break
-    world.wait_for_requirejs(requirements)
 
 
 # Selenium's `execute_async_script` function pauses Selenium's execution
diff --git a/common/static/common/js/utils/page_factory.js b/common/static/common/js/utils/page_factory.js
deleted file mode 100644
index 3ae02bca25583fb10c84e72d634db6c772c0aee1..0000000000000000000000000000000000000000
--- a/common/static/common/js/utils/page_factory.js
+++ /dev/null
@@ -1,27 +0,0 @@
-define([], function() {
-    'use strict';
-
-    return function invokePageFactory(name, factory) {
-        var args;
-
-        if (typeof window.pageFactoryArguments === 'undefined') {
-            throw Error(
-                'window.pageFactoryArguments must be initialized before calling invokePageFactory(' +
-                name +
-                '). Use the <%static:invoke_page_bundle> template tag.'
-            );
-        }
-        args = window.pageFactoryArguments[name];
-
-        if (typeof args === 'undefined') {
-            throw Error(
-                'window.pageFactoryArguments["' +
-                name +
-                '"] must be initialized before calling invokePageFactory(' +
-                name +
-                '). Use the <%static:invoke_page_bundle> template tag.'
-            );
-        }
-        factory.apply(null, window.pageFactoryArguments[name]);
-    };
-});
diff --git a/common/static/common/js/xblock/runtime.v1.js b/common/static/common/js/xblock/runtime.v1.js
index c49d7ea886ddd2dba23ac310ca3062ef69dc48cc..8cf49b5c6cfc73b1fda41486bd7abeb7c85550b8 100644
--- a/common/static/common/js/xblock/runtime.v1.js
+++ b/common/static/common/js/xblock/runtime.v1.js
@@ -1,7 +1,7 @@
 (function() {
     'use strict';
 
-    XBlock.Runtime.v1 = (function() {
+    this.XBlock.Runtime.v1 = (function() {
         function v1() {
             var _this = this;
             this.childMap = function() {
diff --git a/common/test/test-theme/cms/templates/login.html b/common/test/test-theme/cms/templates/login.html
index 4e13b5cdc9e55b3adf49b9c993c55883f54d5abe..ba5d5163b625aa931e4651e9e331571f8ddd56f1 100644
--- a/common/test/test-theme/cms/templates/login.html
+++ b/common/test/test-theme/cms/templates/login.html
@@ -53,7 +53,7 @@ from openedx.core.djangolib.js_utils import js_escaped_string
 </%block>
 
 <%block name="page_bundle">
-  <%static:invoke_page_bundle page_name="js/pages/login" class_name="LoginFactory">
-    "${reverse('homepage') | n, js_escaped_string}"
-  </%static:invoke_page_bundle>
+  <%static:webpack entry="js/factories/login">
+     LoginFactory("${reverse('homepage') | n, js_escaped_string}");
+  </%static:webpack>
 </%block>
diff --git a/package-lock.json b/package-lock.json
index 95235946f15d0d03f7a29016678db76e20ff12ce..70f51cb98d4adddb80b3810e3f93b8a2da7766bc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8219,7 +8219,7 @@
     "redux": {
       "version": "3.7.2",
       "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz",
-      "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==",
+      "integrity": "sha1-BrcxIyFZAdJdBlvjQusCa8HIU3s=",
       "requires": {
         "lodash": "4.17.5",
         "lodash-es": "4.17.6",
diff --git a/scripts/xsslint/xsslint/linters.py b/scripts/xsslint/xsslint/linters.py
index 1ad99e18ca1e38a6ac3ee56ba8c7d85cf266d74c..1c7cc13774aa5c29e762d6b416c02027624b324e 100644
--- a/scripts/xsslint/xsslint/linters.py
+++ b/scripts/xsslint/xsslint/linters.py
@@ -1370,8 +1370,6 @@ class MakoTemplateLinter(BaseLinter):
                 </script> |  # script tag end
                 <%static:require_module(_async)?.*?> |  # require js script tag start (optionally the _async version)
                 </%static:require_module(_async)?> | # require js script tag end (optionally the _async version)
-                <%static:invoke_page_bundle.*?> |  # require js script tag start
-                </%static:invoke_page_bundle> |  # require js script tag end
                 <%static:webpack.*?> |  # webpack script tag start
                 </%static:webpack> | # webpack script tag end
                 <%static:studiofrontend.*?> | # studiofrontend script tag start
diff --git a/themes/red-theme/cms/templates/login.html b/themes/red-theme/cms/templates/login.html
index 721104311d02f0df52b37e40cf1db067ea51ac40..32f564c2a4105fc568e3bb10868f732a8006ad00 100644
--- a/themes/red-theme/cms/templates/login.html
+++ b/themes/red-theme/cms/templates/login.html
@@ -52,7 +52,7 @@ from django.utils.translation import ugettext as _
 </%block>
 
 <%block name="page_bundle">
-  <%static:invoke_page_bundle page_name="js/pages/login" class_name="LoginFactory">
-    "${reverse('homepage') | n, js_escaped_string}"
-  </%static:invoke_page_bundle>
+  <%static:webpack entry="js/factories/login">
+     LoginFactory("${reverse('homepage') | n, js_escaped_string}");
+  </%static:webpack>
 </%block>
diff --git a/webpack.common.config.js b/webpack.common.config.js
index a75a88178107b8efeabba5427fe405af88d9797b..6458225f08c1f9369e2ed21aabdfa18884fbce78 100644
--- a/webpack.common.config.js
+++ b/webpack.common.config.js
@@ -30,11 +30,12 @@ module.exports = {
         // Studio
         Import: './cms/static/js/features/import/factories/import.js',
         CourseOrLibraryListing: './cms/static/js/features_jsx/studio/CourseOrLibraryListing.jsx',
-        'js/pages/login': './cms/static/js/pages/login.js',
-        'js/pages/textbooks': './cms/static/js/pages/textbooks.js',
-        'js/pages/container': './cms/static/js/pages/container.js',
-        'js/pages/library': './cms/static/js/pages/library.js',
-        'js/pages/xblock_validation': './cms/static/js/pages/xblock_validation.js',
+        'js/factories/login': './cms/static/js/factories/login.js',
+        'js/factories/textbooks': './cms/static/js/factories/textbooks.js',
+        'js/factories/container': './cms/static/js/factories/container.js',
+        'js/factories/context_course': './cms/static/js/factories/context_course.js',
+        'js/factories/library': './cms/static/js/factories/library.js',
+        'js/factories/xblock_validation': './cms/static/js/factories/xblock_validation.js',
         'js/sock': './cms/static/js/sock.js',
 
         // LMS