Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

Commit

Permalink
Add support for dynamic filenames (#83)
Browse files Browse the repository at this point in the history
Add support for dynamic filenames
  • Loading branch information
alexdima committed Dec 18, 2019
2 parents dfa3f22 + d71d21e commit e032f77
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 69 deletions.
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -46,8 +46,8 @@ monaco.editor.create(document.getElementById('container'), {

Options can be passed in to `MonacoWebpackPlugin`. They can be used to generate a smaller editor bundle by selecting only certain languages or only certain editor features:

* `output` (`string`) - custom output path for worker scripts, relative to the main webpack `output.path`.
* default value: `''`.
* `filename` (`string`) - custom filename template for worker scripts, respects the same options as [loader-utils' interpolateName](https://github.com/webpack/loader-utils#interpolatename). Useful for adding content-based hashes so that files can be served with long-lived caching headers.
* default value: `'[name].worker.js'`.
* `publicPath` (`string`) - custom public path for worker scripts, overrides the public path from which files generated by this plugin will be served. This wins out over Webpack's dynamic runtime path and can be useful to avoid attempting to load workers cross-origin when using a CDN for other static resources. Use e.g. '/' if you want to load your resources from the current origin..
* default value: `''`.
* `languages` (`string[]`) - include only a subset of the languages supported.
Expand Down
12 changes: 6 additions & 6 deletions index.d.ts
@@ -1,12 +1,6 @@
import { Plugin } from 'webpack'

interface IMonacoEditorWebpackPluginOpts {
/**
* custom output path for worker scripts, relative to the main webpack `output.path`.
* Defaults to ''.
*/
output?: string;

/**
* Include only a subset of the languages supported.
*/
Expand All @@ -18,6 +12,12 @@ interface IMonacoEditorWebpackPluginOpts {
*/
features?: string[];

/**
* Specify a filename template to use for generated files.
* Use e.g. '[name].worker.[contenthash].js' to include content-based hashes.
*/
filename?: string;

/**
* Override the public path from which files generated by this plugin will be served.
* This wins out over Webpack's dynamic runtime path and can be useful to avoid attempting to load workers cross-
Expand Down
36 changes: 25 additions & 11 deletions index.js
@@ -1,5 +1,8 @@
const path = require('path');
const webpack = require('webpack');
const loaderUtils = require('loader-utils');
const fs = require('fs');

const AddWorkerEntryPointPlugin = require('./plugins/AddWorkerEntryPointPlugin');
const INCLUDE_LOADER_PATH = require.resolve('./loaders/include');

Expand All @@ -9,17 +12,28 @@ const EDITOR_MODULE = {
worker: {
id: 'vs/editor/editor',
entry: 'vs/editor/editor.worker',
output: 'editor.worker.js',
fallback: undefined
},
};
const LANGUAGES = require('./languages');
const FEATURES = require('./features');

/**
* Return a resolved path for a given Monaco file.
*/
function resolveMonacoPath(filePath) {
return require.resolve(path.join('monaco-editor/esm', filePath));
}

/**
* Return the interpolated final filename for a worker, respecting the file name template.
*/
function getWorkerFilename(filename, entry) {
return loaderUtils.interpolateName({resourcePath: entry}, filename, {
content: fs.readFileSync(resolveMonacoPath(entry))
});
}

const languagesById = mapValues(LANGUAGES, (language, id) => mixin({ label: id }, language));
const featuresById = mapValues(FEATURES, (feature, key) => mixin({ label: key }, feature))

Expand Down Expand Up @@ -51,20 +65,20 @@ class MonacoWebpackPlugin {
this.options = {
languages: languages.map((id) => languagesById[id]).filter(Boolean),
features: features.map(id => featuresById[id]).filter(Boolean),
output: options.output || '',
publicPath: options.publicPath || ''
filename: options.filename || "[name].worker.js",
publicPath: options.publicPath || '',
};
}

apply(compiler) {
const { languages, features, output, publicPath } = this.options;
const { languages, features, filename, publicPath } = this.options;
const compilationPublicPath = getCompilationPublicPath(compiler);
const modules = [EDITOR_MODULE].concat(languages).concat(features);
const workers = modules.map(
({ label, worker }) => worker && (mixin({ label }, worker))
).filter(Boolean);
const rules = createLoaderRules(languages, features, workers, output, publicPath, compilationPublicPath);
const plugins = createPlugins(workers, output);
const rules = createLoaderRules(languages, features, workers, filename, publicPath, compilationPublicPath);
const plugins = createPlugins(workers, filename);
addCompilerRules(compiler, rules);
addCompilerPlugins(compiler, plugins);
}
Expand All @@ -84,11 +98,11 @@ function getCompilationPublicPath(compiler) {
return compiler.options.output && compiler.options.output.publicPath || '';
}

function createLoaderRules(languages, features, workers, outputPath, pluginPublicPath, compilationPublicPath) {
function createLoaderRules(languages, features, workers, filename, pluginPublicPath, compilationPublicPath) {
if (!languages.length && !features.length) { return []; }
const languagePaths = flatArr(languages.map(({ entry }) => entry).filter(Boolean));
const featurePaths = flatArr(features.map(({ entry }) => entry).filter(Boolean));
const workerPaths = fromPairs(workers.map(({ label, output }) => [label, path.join(outputPath, output)]));
const workerPaths = fromPairs(workers.map(({ label, entry }) => [label, getWorkerFilename(filename, entry)]));
if (workerPaths['typescript']) {
// javascript shares the same worker
workerPaths['javascript'] = workerPaths['typescript'];
Expand Down Expand Up @@ -145,14 +159,14 @@ function createLoaderRules(languages, features, workers, outputPath, pluginPubli
];
}

function createPlugins(workers, outputPath) {
function createPlugins(workers, filename) {
return (
[]
.concat(uniqBy(workers, ({ id }) => id).map(({ id, entry, output }) =>
.concat(uniqBy(workers, ({ id }) => id).map(({ id, entry }) =>
new AddWorkerEntryPointPlugin({
id,
entry: resolveMonacoPath(entry),
filename: path.join(outputPath, output),
filename: getWorkerFilename(filename, entry),
plugins: [
new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }),
],
Expand Down
4 changes: 0 additions & 4 deletions languages.js
Expand Up @@ -39,7 +39,6 @@ module.exports = {
worker: {
id: 'vs/language/css/cssWorker',
entry: 'vs/language/css/css.worker',
output: 'css.worker.js',
fallback: 'vs/language/css/cssWorker',
},
},
Expand Down Expand Up @@ -71,7 +70,6 @@ module.exports = {
worker: {
id: 'vs/language/html/htmlWorker',
entry: 'vs/language/html/html.worker',
output: 'html.worker.js',
fallback: 'vs/language/html/htmlWorker',
},
},
Expand All @@ -92,7 +90,6 @@ module.exports = {
worker: {
id: 'vs/language/json/jsonWorker',
entry: 'vs/language/json/json.worker',
output: 'json.worker.js',
fallback: 'vs/language/json/jsonWorker',
},
},
Expand Down Expand Up @@ -216,7 +213,6 @@ module.exports = {
worker: {
id: 'vs/language/typescript/tsWorker',
entry: 'vs/language/typescript/ts.worker',
output: 'typescript.worker.js',
fallback: 'vs/language/typescript/tsWorker',
},
},
Expand Down

0 comments on commit e032f77

Please sign in to comment.