Webpack in LMS
This commit is contained in:
21
.babelrc
Normal file
21
.babelrc
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"presets": [
|
||||
["env", {
|
||||
"targets": {
|
||||
"browsers": [
|
||||
"last 2 versions",
|
||||
"IE >= 11"
|
||||
]
|
||||
},
|
||||
"useBuiltIns": true,
|
||||
"modules": false,
|
||||
"exclude": [
|
||||
"transform-regenerator"
|
||||
]
|
||||
}],
|
||||
"react"
|
||||
],
|
||||
"plugins": [
|
||||
"transform-object-rest-spread"
|
||||
]
|
||||
}
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -95,6 +95,8 @@ lms/static/css/
|
||||
lms/static/certificates/css/
|
||||
cms/static/css/
|
||||
common/static/common/js/vendor/
|
||||
common/static/bundles
|
||||
webpack-stats.json
|
||||
|
||||
### Styling generated from templates
|
||||
lms/static/sass/*.css
|
||||
|
||||
@@ -85,6 +85,26 @@ engine = Engine(dirs=settings.DEFAULT_TEMPLATE_ENGINE['DIRS'])
|
||||
source, template_path = Loader(engine).load_template_source(path)
|
||||
%>${source | n, decode.utf8}</%def>
|
||||
|
||||
<%def name="webpack(entry)">
|
||||
<%doc>
|
||||
Loads Javascript onto your page from a Webpack-generated bundle.
|
||||
Uses the Django template engine because our webpack loader only provides template tags for Jinja and Django.
|
||||
</%doc>
|
||||
<%
|
||||
from django.template import Template, Context
|
||||
return Template("""
|
||||
{% load render_bundle from webpack_loader %}
|
||||
{% render_bundle entry %}
|
||||
<script type="text/javascript">
|
||||
{% autoescape off %}{{ body }}{% endautoescape %}
|
||||
</script>
|
||||
""").render(Context({
|
||||
'entry': entry,
|
||||
'body': capture(caller.body)
|
||||
}))
|
||||
%>
|
||||
</%def>
|
||||
|
||||
<%def name="require_module(module_name, class_name)">
|
||||
<%doc>
|
||||
Loads Javascript onto your page synchronously.
|
||||
|
||||
@@ -1752,6 +1752,16 @@ REQUIRE_JS_PATH_OVERRIDES = {
|
||||
'hls': 'common/js/vendor/hls.js'
|
||||
}
|
||||
|
||||
########################## DJANGO WEBPACK LOADER ##############################
|
||||
|
||||
WEBPACK_LOADER = {
|
||||
'DEFAULT': {
|
||||
'BUNDLE_DIR_NAME': 'bundles/',
|
||||
'STATS_FILE': os.path.join(REPO_ROOT, 'webpack-stats.json'),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
########################## DJANGO DEBUG TOOLBAR ###############################
|
||||
|
||||
# We don't enable Django Debug Toolbar universally, but whenever we do, we want
|
||||
@@ -1950,6 +1960,7 @@ INSTALLED_APPS = (
|
||||
'edxmako',
|
||||
'pipeline',
|
||||
'static_replace',
|
||||
'webpack_loader',
|
||||
|
||||
# For user interface plugins
|
||||
'web_fragments',
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import * as constants from 'edx-ui-toolkit/src/js/utils/constants';
|
||||
import * as Logger from logger;
|
||||
|
||||
export class CourseOutline {
|
||||
constructor(root) {
|
||||
document.querySelector(root).addEventListener('keydown', (event) => {
|
||||
const focusable = [...document.querySelectorAll('.outline-item.focusable')];
|
||||
const currentFocusIndex = focusable.indexOf(event.target);
|
||||
|
||||
switch (event.keyCode) { // eslint-disable-line default-case
|
||||
case constants.keyCodes.down:
|
||||
event.preventDefault();
|
||||
focusable[Math.min(currentFocusIndex + 1, focusable.length - 1)].focus();
|
||||
break;
|
||||
case constants.keyCodes.up:
|
||||
event.preventDefault();
|
||||
focusable[Math.max(currentFocusIndex - 1, 0)].focus();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelectorAll('a:not([href^="#"])').addEventListener('click', (event) => {
|
||||
Logger.log(
|
||||
'edx.ui.lms.link_clicked',
|
||||
{
|
||||
current_url: window.location.href,
|
||||
target_url: event.currentTarget.href
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
(function(define) {
|
||||
'use strict';
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'logger',
|
||||
'edx-ui-toolkit/js/utils/constants'
|
||||
],
|
||||
function($, Logger, constants) {
|
||||
return function(root) {
|
||||
// In the future this factory could instantiate a Backbone view or React component that handles events
|
||||
$(root).keydown(function(event) {
|
||||
var $focusable = $('.outline-item.focusable'),
|
||||
currentFocusIndex = $.inArray(event.target, $focusable);
|
||||
|
||||
switch (event.keyCode) { // eslint-disable-line default-case
|
||||
case constants.keyCodes.down:
|
||||
event.preventDefault();
|
||||
$focusable.eq(Math.min(currentFocusIndex + 1, $focusable.length - 1)).focus();
|
||||
break;
|
||||
case constants.keyCodes.up:
|
||||
event.preventDefault();
|
||||
$focusable.eq(Math.max(currentFocusIndex - 1, 0)).focus();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
$('a:not([href^="#"])').click(function(event) {
|
||||
Logger.log(
|
||||
'edx.ui.lms.link_clicked',
|
||||
{
|
||||
current_url: window.location.href,
|
||||
target_url: event.currentTarget.href
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
}
|
||||
);
|
||||
}).call(this, define || RequireJS.define);
|
||||
@@ -12,10 +12,6 @@ from django.utils.translation import ugettext as _
|
||||
from openedx.core.djangolib.markup import HTML, Text
|
||||
%>
|
||||
|
||||
<%static:require_module_async module_name="course_experience/js/course_outline_factory" class_name="CourseOutlineFactory">
|
||||
CourseOutlineFactory('.block-tree');
|
||||
</%static:require_module_async>
|
||||
|
||||
<main role="main" class="course-outline" id="main" tabindex="-1">
|
||||
% if blocks.get('children'):
|
||||
<ol class="block-tree" role="tree">
|
||||
@@ -163,3 +159,7 @@ from openedx.core.djangolib.markup import HTML, Text
|
||||
<%static:require_module_async module_name="js/dateutil_factory" class_name="DateUtilFactory">
|
||||
DateUtilFactory.transform('.localized-datetime');
|
||||
</%static:require_module_async>
|
||||
|
||||
<%static:webpack entry="CourseOutline">
|
||||
new CourseOutline('.block-tree');
|
||||
</%static:webpack>
|
||||
|
||||
11
package.json
11
package.json
@@ -20,6 +20,13 @@
|
||||
"underscore.string": "~3.3.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.23.0",
|
||||
"babel-loader": "^6.4.0",
|
||||
"babel-plugin-react": "^1.0.0",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.23.0",
|
||||
"babel-polyfill": "^6.23.0",
|
||||
"babel-preset-env": "^1.2.1",
|
||||
"babel-preset-react": "^6.23.0",
|
||||
"edx-custom-a11y-rules": "0.1.3",
|
||||
"eslint-config-edx": "^2.0.0",
|
||||
"eslint-config-edx-es5": "^2.0.0",
|
||||
@@ -38,6 +45,8 @@
|
||||
"pa11y-reporter-json-oldnode": "1.0.0",
|
||||
"plato": "1.2.2",
|
||||
"sinon": "1.17.3 || >1.17.4 <2.0.0",
|
||||
"squirejs": "^0.1.0"
|
||||
"squirejs": "^0.1.0",
|
||||
"webpack": "^2.2.1",
|
||||
"webpack-bundle-tracker": "^0.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ xmltodict==0.4.1
|
||||
django-ratelimit-backend==1.0
|
||||
unicodecsv==0.9.4
|
||||
django-require==1.0.11
|
||||
django-webpack-loader==0.4.1
|
||||
pyuca==1.1
|
||||
wrapt==1.10.5
|
||||
zendesk==1.1.1
|
||||
|
||||
58
webpack.config.js
Normal file
58
webpack.config.js
Normal file
@@ -0,0 +1,58 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const BundleTracker = require('webpack-bundle-tracker');
|
||||
|
||||
const isProd = process.env.NODE_ENV === 'production';
|
||||
|
||||
const wpconfig = {
|
||||
context: __dirname,
|
||||
|
||||
entry: {
|
||||
CourseOutline: './openedx/features/course_experience/static/course_experience/js/CourseOutline.js',
|
||||
},
|
||||
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'common/static/bundles'),
|
||||
filename: '[name]-[hash].js',
|
||||
libraryTarget: 'window',
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
new webpack.NamedModulesPlugin(),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development'),
|
||||
}),
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
debug: !isProd,
|
||||
}),
|
||||
new BundleTracker({
|
||||
filename: './webpack-stats.json'
|
||||
}),
|
||||
],
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
exclude: /node_modules/,
|
||||
use: 'babel-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.json'],
|
||||
}
|
||||
};
|
||||
|
||||
if (isProd) {
|
||||
wpconfig.plugins = [
|
||||
new webpack.LoaderOptionsPlugin({
|
||||
minimize: true,
|
||||
}),
|
||||
new webpack.optimize.UglifyJsPlugin(),
|
||||
...wpconfig.plugins,
|
||||
];
|
||||
}
|
||||
|
||||
module.exports = wpconfig;
|
||||
Reference in New Issue
Block a user