Browse Source

Azure Monitor: build monaco with webpack WIP

Alexander Zobnin 7 years ago
parent
commit
00de497663

+ 3 - 0
package.json

@@ -16,6 +16,7 @@
     "@babel/preset-env": "^7.1.0",
     "@babel/preset-react": "^7.0.0",
     "@babel/preset-typescript": "^7.1.0",
+    "@kusto/monaco-kusto": "https://github.com/grafana/monaco-kusto",
     "@rtsao/plugin-proposal-class-properties": "^7.0.1-patch.1",
     "@types/classnames": "^2.2.6",
     "@types/d3": "^4.10.1",
@@ -83,6 +84,7 @@
     "prettier": "1.9.2",
     "react-hot-loader": "^4.3.6",
     "react-test-renderer": "^16.5.0",
+    "regexp-replace-loader": "^1.0.1",
     "sass-lint": "^1.10.2",
     "sass-loader": "^7.0.1",
     "sinon": "1.17.6",
@@ -97,6 +99,7 @@
     "tslint-react": "^3.6.0",
     "typescript": "^3.0.3",
     "uglifyjs-webpack-plugin": "^1.2.7",
+    "vscode-languageserver-types": "^3.14.0",
     "webpack": "4.19.1",
     "webpack-bundle-analyzer": "^2.9.0",
     "webpack-cleanup-plugin": "^0.5.1",

File diff suppressed because it is too large
+ 0 - 0
public/app/plugins/datasource/grafana-azure-monitor-datasource/lib/monaco.min.js


+ 2 - 0
public/app/plugins/datasource/grafana-azure-monitor-datasource/monaco/kusto_code_editor.ts

@@ -57,11 +57,13 @@ export default class KustoCodeEditor {
       includeControlCommands: true,
       newlineAfterPipe: true,
       useIntellisenseV2: false,
+      useSemanticColorization: true,
     });
 
     this.codeEditor = monaco.editor.create(this.containerDiv, {
       value: scope.content || 'Write your query here',
       language: 'kusto',
+      // language: 'go',
       selectionHighlight: false,
       theme: themeName,
       folding: true,

+ 17 - 2
public/app/plugins/datasource/grafana-azure-monitor-datasource/monaco/kusto_monaco_editor.ts

@@ -1,17 +1,32 @@
 // tslint:disable-next-line:no-reference
-///<reference path="../../../../../../node_modules/monaco-editor/monaco.d.ts" />
+// ///<reference path="../../../../../../node_modules/monaco-editor/monaco.d.ts" />
 
 import angular from 'angular';
 import KustoCodeEditor from './kusto_code_editor';
 import config from 'app/core/config';
 
+/**
+ * Load monaco code editor and its' dependencies as a separate webpack chunk.
+ */
+function importMonaco() {
+  return import(
+    /* webpackChunkName: "monaco" */
+    './monaco-loader'
+  ).then(monaco => {
+    return monaco;
+  }).catch(error => {
+    console.error('An error occurred while loading monaco-kusto:\n', error);
+  });
+}
+
 const editorTemplate = `<div id="content" tabindex="0" style="width: 100%; height: 120px"></div>`;
 
 function link(scope, elem, attrs) {
   const containerDiv = elem.find('#content')[0];
 
   if (!(global as any).monaco) {
-    (global as any).System.import(`./${scope.pluginBaseUrl}/lib/monaco.min.js`).then(() => {
+    // (global as any).System.import(`./${scope.pluginBaseUrl}/lib/monaco.min.js`).then(() => {
+    importMonaco().then(() => {
       setTimeout(() => {
         initMonaco(containerDiv, scope);
       }, 1);

+ 21 - 0
public/app/plugins/datasource/grafana-azure-monitor-datasource/monaco/monaco-loader.ts

@@ -0,0 +1,21 @@
+// tslint:disable:no-reference
+// ///<reference path="../../../../../../node_modules/@kusto/monaco-kusto/release/min/monaco.d.ts" />
+
+// (1) Desired editor features:
+import "monaco-editor/esm/vs/editor/browser/controller/coreCommands.js";
+import 'monaco-editor/esm/vs/editor/browser/widget/codeEditorWidget.js';
+import 'monaco-editor/esm/vs/editor/contrib/contextmenu/contextmenu.js';
+import "monaco-editor/esm/vs/editor/contrib/find/findController.js";
+import 'monaco-editor/esm/vs/editor/contrib/folding/folding.js';
+import 'monaco-editor/esm/vs/editor/contrib/format/formatActions.js';
+import 'monaco-editor/esm/vs/editor/contrib/multicursor/multicursor.js';
+import 'monaco-editor/esm/vs/editor/contrib/suggest/suggestController.js';
+import 'monaco-editor/esm/vs/editor/contrib/wordHighlighter/wordHighlighter.js';
+import 'monaco-editor/esm/vs/editor/standalone/browser/iPadShowKeyboard/iPadShowKeyboard.js';
+import "monaco-editor/esm/vs/editor/editor.api.js";
+
+// (2) Desired languages:
+import '@kusto/monaco-kusto/release/webpack/bridge.min.js';
+import '@kusto/monaco-kusto/release/webpack/Kusto.JavaScript.Client.min.js';
+import '@kusto/monaco-kusto/release/webpack/Kusto.Language.Bridge.min.js';
+import '@kusto/monaco-kusto/release/webpack/monaco.contribution.min.js';

+ 6 - 0
scripts/webpack/loaders/blobUrl.js

@@ -0,0 +1,6 @@
+const loaderUtils = require('loader-utils');
+
+module.exports = function blobUrl(source) {
+  const { type } = loaderUtils.getOptions(this) || {};
+  return `module.exports = URL.createObjectURL(new Blob([${JSON.stringify(source)}]${type ? `, { type: ${JSON.stringify(type)} }` : ''}));`;
+};

+ 87 - 0
scripts/webpack/loaders/compile.js

@@ -0,0 +1,87 @@
+const loaderUtils = require('loader-utils');
+
+const WebWorkerTemplatePlugin = require('webpack/lib/webworker/WebWorkerTemplatePlugin');
+const ExternalsPlugin = require('webpack/lib/ExternalsPlugin');
+const NodeTargetPlugin = require('webpack/lib/node/NodeTargetPlugin');
+const LoaderTargetPlugin = require('webpack/lib/LoaderTargetPlugin');
+const SingleEntryPlugin = require('webpack/lib/SingleEntryPlugin');
+
+const COMPILATION_METADATA = Symbol('COMPILATION_METADATA');
+
+module.exports.COMPILATION_METADATA = COMPILATION_METADATA;
+
+module.exports.pitch = function pitch(remainingRequest) {
+  const { target, plugins = [], output, emit } = loaderUtils.getOptions(this) || {};
+
+  if (target !== 'worker') {
+    throw new Error(`Unsupported compile target: ${JSON.stringify(target)}`);
+  }
+
+  this.cacheable(false);
+
+  const { filename, options = {} } = getOutputFilename(output, { target });
+
+  // eslint-disable-next-line no-underscore-dangle
+  const currentCompilation = this._compilation;
+
+  const outputFilename = loaderUtils.interpolateName(this, filename, {
+    context: options.context || currentCompilation.options.context,
+    regExp: options.regExp,
+  });
+
+  const outputOptions = {
+    filename: outputFilename,
+    chunkFilename: `${outputFilename}.[id]`,
+    namedChunkFilename: null,
+  };
+
+  const compilerOptions = currentCompilation.compiler.options;
+  const childCompiler = currentCompilation.createChildCompiler('worker', outputOptions, [
+    // https://github.com/webpack/webpack/blob/master/lib/WebpackOptionsApply.js
+    new WebWorkerTemplatePlugin(outputOptions),
+    new LoaderTargetPlugin('webworker'),
+    ...((this.target === 'web') || (this.target === 'webworker') ? [] : [new NodeTargetPlugin()]),
+
+    // https://github.com/webpack-contrib/worker-loader/issues/95#issuecomment-352856617
+    ...(compilerOptions.externals ? [new ExternalsPlugin(compilerOptions.externals)] : []),
+
+    ...plugins,
+
+    new SingleEntryPlugin(this.context, `!!${remainingRequest}`, 'main'),
+  ]);
+
+  const subCache = `subcache ${__dirname} ${remainingRequest}`;
+
+  childCompiler.plugin('compilation', (compilation) => {
+    if (!compilation.cache) { return; }
+    if (!(subCache in compilation.cache)) { Object.assign(compilation.cache, { [subCache]: {} }); }
+    Object.assign(compilation, { cache: compilation.cache[subCache] });
+  });
+
+  const callback = this.async();
+
+  childCompiler.runAsChild((error, entries, compilation) => {
+    if (error) { return callback(error); }
+    if (entries.length === 0) { return callback(null, null); }
+    const mainFilename = entries[0].files[0];
+    if (emit === false) { delete currentCompilation.assets[mainFilename]; }
+    callback(null, compilation.assets[mainFilename].source(), null, {
+      [COMPILATION_METADATA]: entries[0].files,
+    });
+  });
+};
+
+function getOutputFilename(options, { target }) {
+  if (!options) { return { filename: `[hash].${target}.js`, options: undefined }; }
+  if (typeof options === 'string') { return { filename: options, options: undefined }; }
+  if (typeof options === 'object') {
+    return {
+      filename: options.filename,
+      options: {
+        context: options.context,
+        regExp: options.regExp,
+      },
+    };
+  }
+  throw new Error(`Invalid compile output options: ${options}`);
+}

+ 2 - 1
scripts/webpack/webpack.dev.js

@@ -2,6 +2,7 @@
 
 const merge = require('webpack-merge');
 const common = require('./webpack.common.js');
+const monaco = require('./webpack.monaco.js');
 const path = require('path');
 const webpack = require('webpack');
 const HtmlWebpackPlugin = require("html-webpack-plugin");
@@ -9,7 +10,7 @@ const CleanWebpackPlugin = require('clean-webpack-plugin');
 const MiniCssExtractPlugin = require("mini-css-extract-plugin");
 // const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
 
-module.exports = merge(common, {
+module.exports = merge(common, monaco, {
   devtool: "cheap-module-source-map",
   mode: 'development',
 

+ 122 - 0
scripts/webpack/webpack.monaco.js

@@ -0,0 +1,122 @@
+const path = require('path');
+const webpack = require('webpack');
+const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
+
+module.exports = {
+  // output: {
+  //   filename: 'monaco.min.js',
+  //   path: path.resolve(__dirname, 'dist'),
+  //   libraryTarget: 'umd',
+  //   library: 'monaco',
+  //   globalObject: 'self'
+  // },
+  entry: {
+    // monaco: './public/app/plugins/datasource/grafana-azure-monitor-datasource/monaco/monaco-loader.ts',
+  },
+  output: {
+    // filename: 'monaco.min.js',
+    // chunkFilename: '[name].bundle.js',
+    globalObject: 'self',
+  },
+  resolveLoader: {
+    alias: {
+      'blob-url-loader': require.resolve('./loaders/blobUrl'),
+      'compile-loader': require.resolve('./loaders/compile'),
+    },
+  },
+  module: {
+    rules: [
+      {
+        test: /\.css$/,
+        use: [ 'style-loader', 'css-loader' ]
+      },
+      // {
+      //   // https://github.com/bridgedotnet/Bridge/issues/3097
+      //   test: /bridge\.js$/,
+      //   loader: 'regexp-replace-loader',
+      //   options: {
+      //     match: {
+      //       pattern: "globals\\.System\\s=\\s\\{\\};"
+      //     },
+      //     replaceWith: "$& System = globals.System; "
+      //   }
+      // },
+      // {
+      //   test: /Kusto\.JavaScript\.Client\.js$/,
+      //   loader: 'regexp-replace-loader',
+      //   options: {
+      //     match: {
+      //       pattern: '"use strict";'
+      //     },
+      //     replaceWith: "$& System = globals.System; "
+      //   }
+      // },
+      // {
+      //   test: /Kusto\.Language\.Bridge\.js$/,
+      //   loader: 'regexp-replace-loader',
+      //   options: {
+      //     match: {
+      //       pattern: '"use strict";'
+      //     },
+      //     replaceWith: "$& System = globals.System; "
+      //   }
+      // },
+      // {
+      //   test: /newtonsoft\.json\.js$/,
+      //   loader: 'regexp-replace-loader',
+      //   options: {
+      //     match: {
+      //       pattern: '"use strict";'
+      //     },
+      //     replaceWith: "$& System = globals.System; "
+      //   }
+      // },
+      // {
+      //   test: /monaco\.contribution\.js$/,
+      //   loader: 'regexp-replace-loader',
+      //   options: {
+      //     match: {
+      //       pattern: 'vs/language/kusto/kustoMode',
+      //       flags: 'g'
+      //     },
+      //     replaceWith: "./kustoMode"
+      //   }
+      // },
+    ]
+  },
+  optimization: {
+    splitChunks: {
+      // chunks: 'all',
+      cacheGroups: {
+        // monacoContribution: {
+        //   test: /(src)|(node_modules(?!\/@kusto))/,
+        //   name: 'monaco.contribution',
+        //   enforce: false,
+        //   // chunks: 'all',
+        // },
+        // bridge: {
+        //   test: /bridge/,
+        //   name: 'bridge',
+        //   chunks: 'all',
+        // },
+        // KustoJavaScriptClient: {
+        //   test: /Kusto\.JavaScript\.Client/,
+        //   name: 'kusto.javaScript.client',
+        //   chunks: 'all',
+        // },
+        // KustoLanguageBridge: {
+        //   test: /Kusto\.Language\.Bridge/,
+        //   name: 'kusto.language.bridge',
+        //   chunks: 'all',
+        // },
+      }
+    }
+  },
+  plugins: [
+    new webpack.IgnorePlugin(/^((fs)|(path)|(os)|(crypto)|(source-map-support))$/, /vs\/language\/typescript\/lib/),
+    // new webpack.optimize.LimitChunkCountPlugin({
+    //   maxChunks: 1,
+    // }),
+    // new UglifyJSPlugin()
+  ],
+};

+ 29 - 0
yarn.lock

@@ -654,6 +654,23 @@
   version "0.8.2"
   resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-0.8.2.tgz#576ff7fb1230185b619a75d258cbc98f0867a8dc"
 
+"@kusto/language-service-next@0.0.25-alpha1":
+  version "0.0.25-alpha1"
+  resolved "https://registry.yarnpkg.com/@kusto/language-service-next/-/language-service-next-0.0.25-alpha1.tgz#73977b0873c7c2a23ae0c2cc1fef95a68c723c09"
+  integrity sha512-xxdY+Ei+e/GuzWZYoyjQqOfuzwVPMfHJwPRcxOdcSq5XMt9oZS+ryVH66l+CBxdZDdxEfQD2evVTXLjOAck5Rg==
+
+"@kusto/language-service@0.0.22-alpha":
+  version "0.0.22-alpha"
+  resolved "https://registry.yarnpkg.com/@kusto/language-service/-/language-service-0.0.22-alpha.tgz#990bbfb82e8e8991c35a12aab00d890a05fff623"
+  integrity sha512-oYiakH2Lq4j7ghahAtqxC+nuOKybH03H1o3IWyB3p8Ll4WkYQOrV8GWpqEjPtMfsuOt3t5k55OzzwDWFaX2zlw==
+
+"@kusto/monaco-kusto@https://github.com/grafana/monaco-kusto":
+  version "0.2.2"
+  resolved "https://github.com/grafana/monaco-kusto#877c1a5003510af51636281a7ce36ad3731c458a"
+  dependencies:
+    "@kusto/language-service" "0.0.22-alpha"
+    "@kusto/language-service-next" "0.0.25-alpha1"
+
 "@mrmlnc/readdir-enhanced@^2.2.1":
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
@@ -10907,6 +10924,13 @@ regex-not@^1.0.0, regex-not@^1.0.2:
     extend-shallow "^3.0.2"
     safe-regex "^1.1.0"
 
+regexp-replace-loader@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/regexp-replace-loader/-/regexp-replace-loader-1.0.1.tgz#5dae73be9ee82a4d94d0955c2fa3fc923e134d7e"
+  integrity sha1-Xa5zvp7oKk2U0JVcL6P8kj4TTX4=
+  dependencies:
+    loader-utils "^1.0.2"
+
 regexpu-core@^1.0.0:
   version "1.0.0"
   resolved "http://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz#86a763f58ee4d7c2f6b102e4764050de7ed90c6b"
@@ -12954,6 +12978,11 @@ vm-browserify@0.0.4:
   dependencies:
     indexof "0.0.1"
 
+vscode-languageserver-types@^3.14.0:
+  version "3.14.0"
+  resolved "https://registry.yarnpkg.com/vscode-languageserver-types/-/vscode-languageserver-types-3.14.0.tgz#d3b5952246d30e5241592b6dde8280e03942e743"
+  integrity sha512-lTmS6AlAlMHOvPQemVwo3CezxBp0sNB95KNPkqp3Nxd5VFEnuG1ByM0zlRWos0zjO3ZWtkvhal0COgiV1xIA4A==
+
 w3c-blob@0.0.1:
   version "0.0.1"
   resolved "https://registry.yarnpkg.com/w3c-blob/-/w3c-blob-0.0.1.tgz#b0cd352a1a50f515563420ffd5861f950f1d85b8"

Some files were not shown because too many files changed in this diff