rollup-plugin-web-worker-loader
Advanced tools
Comparing version 1.1.3 to 1.2.0
{ | ||
"name": "rollup-plugin-web-worker-loader", | ||
"version": "1.1.3", | ||
"version": "1.2.0", | ||
"description": "Rollup plugin to handle Web Workers", | ||
@@ -5,0 +5,0 @@ "main": "src/index.js", |
276
src/index.js
@@ -1,31 +0,36 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const rollup = require('rollup'); | ||
const fixMapSources = require('./utils/fixMapSources'); | ||
const extractSource = require('./utils/extractSource'); | ||
const buildWorkerCode = require('./utils/buildWorkerCode'); | ||
const options = require('./plugin/options'); | ||
const resolveId = require('./plugin/resolveId'); | ||
const load = require('./plugin/load'); | ||
const transform = require('./plugin/transform'); | ||
const outputOptions = require('./plugin/outputOptions'); | ||
const generateBundle = require('./plugin/generateBundle'); | ||
module.exports = function workerLoaderPlugin(config = null) { | ||
const targetPlatform = config && config.hasOwnProperty('targetPlatform') ? config.targetPlatform : 'auto'; | ||
const sourcemap = config && config.hasOwnProperty('sourcemap') ? config.sourcemap : false; | ||
const loadPath = config && config.hasOwnProperty('loadPath') ? config.loadPath : ''; | ||
const preserveSource = config && config.hasOwnProperty('preserveSource') ? config.preserveSource : false; | ||
const enableUnicode = config && config.hasOwnProperty('enableUnicodeSupport') ? config.enableUnicodeSupport : false; | ||
const pattern = config && config.hasOwnProperty('pattern') ? config.pattern : /web-worker:(.+)/; | ||
const skipPlugins = new Set(config && config.hasOwnProperty('skipPlugins') ? config.skipPlugins : [ | ||
const defaultConfig = { | ||
targetPlatform: 'auto', | ||
sourcemap: 'false', | ||
loadPath: '', | ||
preserveSource: false, | ||
enableUnicode: false, | ||
pattern: /web-worker:(.+)/, | ||
inline: true, | ||
forceInline: false, | ||
skipPlugins: [ | ||
'liveServer', | ||
'serve', | ||
'livereload', | ||
]); | ||
], | ||
}; | ||
let inline = config && config.hasOwnProperty('inline') ? config.inline : true; | ||
const forceInline = inline && config && config.hasOwnProperty('forceInline') ? config.forceInline : false; | ||
module.exports = function workerLoaderPlugin(userConfig = null) { | ||
const config = Object.assign({}, defaultConfig, userConfig); | ||
config.skipPlugins = new Set(config.skipPlugins); | ||
const helperPattern = /^\0(?:[0-9]+::)?rollup-plugin-web-worker-loader::helper(?:::)?/; | ||
const idMap = new Map(); | ||
const exclude = new Set(); | ||
let projectOptions = null; | ||
let basePath = null; | ||
let configuredFileName = null; | ||
let forceInlineCounter = 0; | ||
const state = { | ||
idMap: new Map(), | ||
exclude: new Set(), | ||
options: null, | ||
basePath: null, | ||
forceInlineCounter: 0, | ||
configuredFileName: null, | ||
}; | ||
@@ -35,235 +40,26 @@ return { | ||
options(options) { | ||
if (!projectOptions) { | ||
projectOptions = Object.assign({}, options); | ||
if (options.plugins && options.plugins.length) { | ||
const plugins = []; | ||
options.plugins.forEach(plugin => { | ||
if (skipPlugins.has(plugin.name)) return; | ||
plugins.push(plugin); | ||
}); | ||
projectOptions.plugins = plugins; | ||
const cwd = process.cwd(); | ||
if (typeof options.input === 'string') { | ||
try { | ||
const entry = require.resolve(options.input, { paths: [cwd] }); | ||
basePath = path.dirname(entry); | ||
} catch (e) { /* EMPTY */ } | ||
} else if (Array.isArray(options.input)) { | ||
let componentCount = Number.MAX_SAFE_INTEGER; | ||
let shortestPath = null; | ||
for (let i = 0, n = options.input.length; i < n; ++i) { | ||
try { | ||
const entry = require.resolve(options.input[i], { paths: [cwd] }); | ||
const entryPath = path.dirname(entry); | ||
const components = entryPath.split(path.sep); | ||
if (components.length < componentCount) { | ||
componentCount = components.length; | ||
shortestPath = entryPath; | ||
} | ||
} catch (e) { /* EMPTY */ } | ||
} | ||
basePath = shortestPath; | ||
} else { | ||
const keys = Object.keys(options.input); | ||
let componentCount = Number.MAX_SAFE_INTEGER; | ||
let shortestPath = null; | ||
for (let i = 0, n = keys.length; i < n; ++i) { | ||
const input = options.input[keys[i]]; | ||
try { | ||
const entry = require.resolve(input, { paths: [cwd] }); | ||
const entryPath = path.dirname(entry); | ||
const components = entryPath.split(path.sep); | ||
if (components.length < componentCount) { | ||
componentCount = components.length; | ||
shortestPath = entryPath; | ||
} | ||
} catch (e) { /* EMPTY */ } | ||
} | ||
basePath = shortestPath; | ||
} | ||
if (!basePath) { | ||
basePath = '.'; | ||
} | ||
} | ||
} | ||
return null; | ||
options(optionsArg) { | ||
return options(state, config, optionsArg); | ||
}, | ||
resolveId(importee, importer) { | ||
const match = importee.match(pattern); | ||
if (importee.startsWith('\0rollup-plugin-web-worker-loader::helper')) { | ||
if (forceInline) { | ||
return `\0${forceInlineCounter++}::${importee.substr(1)}`; | ||
} | ||
return importee; | ||
} else if (match && match.length) { | ||
const name = match[match.length - 1]; | ||
if (!idMap.has(name)) { | ||
let target = null; | ||
if (importer) { | ||
const folder = path.dirname(importer); | ||
const paths = require.resolve.paths(importer); | ||
paths.push(folder); | ||
target = require.resolve(name, {paths}); | ||
} else if (path.isAbsolute(name)) { | ||
target = name; | ||
} | ||
if (target) { | ||
const prefixed = `\0rollup-plugin-worker-loader::module:${forceInline ? `:${forceInlineCounter++}:` : ''}${name}`; | ||
if (!idMap.has(prefixed)) { | ||
const inputOptions = Object.assign({}, projectOptions, { | ||
input: target, | ||
}); | ||
idMap.set(prefixed, { | ||
workerID: `web-worker-${idMap.size}.js`, | ||
chunk: null, | ||
inputOptions, | ||
target, | ||
}); | ||
} | ||
if (idMap.has(prefixed)) { | ||
return prefixed; | ||
} | ||
return target; | ||
} | ||
} | ||
} | ||
return null; | ||
return resolveId(state, config, importee, importer); | ||
}, | ||
load(id) { | ||
return new Promise((resolve, reject) => { | ||
const helperMatch = helperPattern.exec(id); | ||
if (helperMatch) { | ||
const helperParts = id.substr(helperMatch[0].length).split('::'); | ||
const helperPath = path.resolve(__dirname, 'helper', ...helperParts) + '.js'; | ||
fs.readFile(helperPath, 'utf8', (err, data) => { | ||
if (err) { | ||
reject(err); | ||
} | ||
resolve(data); | ||
}); | ||
} else if (idMap.has(id) && !exclude.has(id)) { | ||
if (!inline) { | ||
/* inline requires rollup version 1.9.2 or higher */ | ||
const version = this.meta.rollupVersion.split('.'); | ||
if (version.length !== 3) { | ||
this.warn('Unknown rollup version'); | ||
inline = true; | ||
} else { | ||
const major = parseInt(version[0], 10); | ||
const minor = parseInt(version[1], 10); | ||
const patch = parseInt(version[2], 10); | ||
if ( | ||
isNaN(major) || | ||
isNaN(minor) || | ||
isNaN(patch) || | ||
major < 1 || | ||
(major === 1 && minor < 9) || | ||
(major === 1 && minor === 9 && patch < 2) | ||
) { | ||
this.warn(`Rollup version 1.9.2 or higher is required for emitting a worker file (current version:${this.meta.rollupVersion}). See https://github.com/rollup/rollup/issues/2801`); | ||
inline = true; | ||
} | ||
} | ||
} | ||
const {inputOptions, workerID, target} = idMap.get(id); | ||
exclude.add(id); | ||
exclude.add(target); | ||
rollup.rollup(inputOptions).then(bundle => { | ||
exclude.delete(id); | ||
exclude.delete(target); | ||
bundle.generate({format: 'es', name: id, sourcemap: true}).then(result => { | ||
const output = result.output; | ||
let chunk = null; | ||
for (const ch of output) { | ||
if (!ch.isAsset) { | ||
chunk = ch; | ||
break; | ||
} | ||
} | ||
if (chunk !== null) { | ||
/* add dependencies to watch list */ | ||
const deps = Object.keys(chunk.modules); | ||
for (const dep of deps) { | ||
this.addWatchFile(dep); | ||
} | ||
let map = null; | ||
let source; | ||
if (inline) { | ||
source = extractSource(chunk.code, chunk.exports, preserveSource); | ||
map = null; | ||
if (sourcemap) { | ||
map = fixMapSources(chunk, basePath); | ||
} | ||
} else { | ||
source = path.posix.join(loadPath, workerID); | ||
chunk.fileName = workerID; | ||
idMap.get(id).chunk = chunk; | ||
} | ||
resolve({ | ||
code: buildWorkerCode(source, map, { | ||
inline, | ||
preserveSource, | ||
enableUnicode, | ||
targetPlatform, | ||
}), | ||
}); | ||
} else { | ||
resolve(null); | ||
} | ||
}).catch(reject); | ||
}).catch(reason => { | ||
exclude.delete(id); | ||
exclude.delete(target); | ||
reject(reason); | ||
}); | ||
} else { | ||
resolve(null); | ||
} | ||
}); | ||
return load(state, config, this.addWatchFile, id); | ||
}, | ||
transform(code, id) { | ||
if (idMap.has(id) && !exclude.has(id)) { | ||
const {inputOptions} = idMap.get(id); | ||
return { code, map: `{"version":3,"file":"${path.basename(inputOptions.input)}","sources":[],"sourcesContent":[],"names":[],"mappings":""}` }; | ||
} | ||
return null; | ||
return transform(state, config, code, id); | ||
}, | ||
outputOptions(options) { | ||
if (!inline && options.file && !options.dir) { | ||
configuredFileName = path.basename(options.file); | ||
return Object.assign({}, options, { | ||
file: null, | ||
dir: path.dirname(options.file), | ||
}); | ||
} | ||
return null; | ||
return outputOptions(state, config, options); | ||
}, | ||
generateBundle(options, bundle, isWrite) { | ||
if (!inline && isWrite) { | ||
if (configuredFileName && Object.keys(bundle).length === 1) { | ||
bundle[Object.keys(bundle)[0]].fileName = configuredFileName; | ||
} | ||
for (const worker of idMap) { | ||
if (worker[1].chunk && !bundle[worker[1].workerID]) { | ||
bundle[worker[1].workerID] = worker[1].chunk; | ||
} | ||
} | ||
} | ||
generateBundle(state, config, options, bundle, isWrite); | ||
}, | ||
}; | ||
}; |
28
521
46465