]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Make moment optional from our UMD builds (#5978)
authorSimon Brunel <simonbrunel@users.noreply.github.com>
Tue, 29 Jan 2019 16:54:22 +0000 (17:54 +0100)
committerGitHub <noreply@github.com>
Tue, 29 Jan 2019 16:54:22 +0000 (17:54 +0100)
docs/getting-started/integration.md
package.json
rollup.config.js
rollup.plugins.js [new file with mode: 0644]

index 285bf195b922041eaf0edc9e30f390e2dea38862..71e7d28ef08d3dd3b4e150d73825075acfcf19e1 100644 (file)
@@ -11,26 +11,76 @@ Chart.js can be integrated with plain JavaScript or with different module loader
 </script>
 ```
 
-## Webpack
+## Common JS
 
 ```javascript
-import Chart from 'chart.js';
+var Chart = require('chart.js');
 var myChart = new Chart(ctx, {...});
 ```
 
-## Common JS
+## Bundlers (Webpack, Rollup, etc.)
 
 ```javascript
-var Chart = require('chart.js');
+import Chart from 'chart.js';
 var myChart = new Chart(ctx, {...});
 ```
 
+**Note:** Moment.js is installed along Chart.js as dependency. If you don't want to use Momemt.js (either because you use a different date adapter or simply because don't need time functionalities), you will have to configure your bundler to exclude this dependency (e.g. using [`externals` for Webpack](https://webpack.js.org/configuration/externals/) or [`external` for Rollup](https://rollupjs.org/guide/en#peer-dependencies)).
+
+```javascript
+// Webpack
+{
+    externals: {
+        moment: 'moment'
+    }
+}
+```
+
+```javascript
+// Rollup
+{
+    external: {
+        ['moment']
+    }
+}
+```
+
 ## Require JS
 
+**Important:** RequireJS [can **not** load CommonJS module as is](https://requirejs.org/docs/commonjs.html#intro), so be sure to require one of the UMD builds instead (i.e. `dist/Chart.js`, `dist/Chart.min.js`, etc.).
+
 ```javascript
-require(['path/to/chartjs/dist/Chart.js'], function(Chart) {
+require(['path/to/chartjs/dist/Chart.min.js'], function(Chart){
     var myChart = new Chart(ctx, {...});
 });
 ```
 
-> **Important:** RequireJS [can **not** load CommonJS module as is](https://requirejs.org/docs/commonjs.html#intro), so be sure to require one of the built UMD files instead (i.e. `dist/Chart.js`, `dist/Chart.min.js`, etc.).
+**Note:** starting v2.8, Moment.js is an optional dependency for `Chart.js` and `Chart.min.js`. In order to use the time scale with Moment.js, you need to make sure Moment.js is fully loaded **before** requiring Chart.js. You can either use a shim:
+
+```javascript
+require.config({
+    shim: {
+        'chartjs': {
+            deps: ['moment']    // enforce moment to be loaded before chartjs
+        }
+    },
+    paths: {
+        'chartjs': 'path/to/chartjs/dist/Chart.min.js',
+        'moment': 'path/to/moment'
+    }
+});
+
+require(['chartjs'], function(Chart) {
+    new Chart(ctx, {...});
+});
+```
+
+or simply use two nested `require()`:
+
+```javascript
+require(['moment'], function() {
+    require(['chartjs'], function(Chart) {
+        new Chart(ctx, {...});
+    });
+});
+```
index bf913bf0aee3ddf9e6a82cf5dae9ff929999649a..0062c3e93e8801b13acd9c8e20124f9787c9d6e6 100644 (file)
@@ -6,7 +6,7 @@
   "license": "MIT",
   "jsdelivr": "dist/Chart.min.js",
   "unpkg": "dist/Chart.min.js",
-  "main": "src/chart.js",
+  "main": "dist/Chart.js",
   "keywords": [
     "canvas",
     "charts",
index 9f76d9573174bfc2dd7ca88d5bce7fb59ff175aa..83ae38d67c5c93d5025d1250d747034051cf12cb 100644 (file)
@@ -3,6 +3,7 @@
 const commonjs = require('rollup-plugin-commonjs');
 const resolve = require('rollup-plugin-node-resolve');
 const terser = require('rollup-plugin-terser').terser;
+const optional = require('./rollup.plugins').optional;
 const pkg = require('./package.json');
 
 const input = 'src/chart.js';
@@ -21,7 +22,10 @@ module.exports = [
                input: input,
                plugins: [
                        resolve(),
-                       commonjs()
+                       commonjs(),
+                       optional({
+                               include: ['moment']
+                       })
                ],
                output: {
                        name: 'Chart',
@@ -42,6 +46,9 @@ module.exports = [
                plugins: [
                        resolve(),
                        commonjs(),
+                       optional({
+                               include: ['moment']
+                       }),
                        terser({
                                output: {
                                        preamble: banner
diff --git a/rollup.plugins.js b/rollup.plugins.js
new file mode 100644 (file)
index 0000000..39c7570
--- /dev/null
@@ -0,0 +1,61 @@
+/* eslint-env es6 */
+
+const UMD_WRAPPER_RE = /(\(function \(global, factory\) \{)((?:\s.*?)*)(\}\(this,)/;
+const CJS_FACTORY_RE = /(module.exports = )(factory\(.*?\))( :)/;
+const AMD_FACTORY_RE = /(define\()(.*?, factory)(\) :)/;
+
+function optional(config = {}) {
+       return {
+               name: 'optional',
+               renderChunk(code, chunk, options) {
+                       if (options.format !== 'umd') {
+                               this.error('only UMD format is currently supported');
+                       }
+
+                       const wrapper = UMD_WRAPPER_RE.exec(code);
+                       const include = config.include;
+                       if (!wrapper) {
+                               this.error('failed to parse the UMD wrapper');
+                       }
+
+                       let content = wrapper[2];
+                       let factory = (CJS_FACTORY_RE.exec(content) || [])[2];
+                       let updated = false;
+
+                       for (let lib of chunk.imports) {
+                               if (!include || include.indexOf(lib) !== -1) {
+                                       const regex = new RegExp(`require\\('${lib}'\\)`);
+                                       if (!regex.test(factory)) {
+                                               this.error(`failed to parse the CJS require for ${lib}`);
+                                       }
+
+                                       // We need to write inline try / catch with explicit require
+                                       // in order to enable statical extraction of dependencies:
+                                       // try { return require('moment'); } catch(e) {}
+                                       const loader = `function() { try { return require('${lib}'); } catch(e) { } }()`;
+                                       factory = factory.replace(regex, loader);
+                                       updated = true;
+                               }
+                       }
+
+                       if (!updated) {
+                               return;
+                       }
+
+                       // Replace the CJS factory by our updated one.
+                       content = content.replace(CJS_FACTORY_RE, `$1${factory}$3`);
+
+                       // Replace the AMD factory by our updated one: we need to use the
+                       // following AMD form in order to be able to try/catch require:
+                       // define(['require'], function(require) { ... require(...); ... })
+                       // https://github.com/amdjs/amdjs-api/wiki/AMD#using-require-and-exports
+                       content = content.replace(AMD_FACTORY_RE, `$1['require'], function(require) { return ${factory}; }$3`);
+
+                       return code.replace(UMD_WRAPPER_RE, `$1${content}$3`);
+               }
+       };
+}
+
+module.exports = {
+       optional
+};