|
| 1 | +/* |
| 2 | +Inter-loader Option idToOptions |
| 3 | +
|
| 4 | +Vue-loader works by delegating language blocks to sub-loaders. |
| 5 | +The main loader needs to share its options object with the sub-loaders. |
| 6 | +Technically we should pass everything the sub loaders need via their own |
| 7 | +options, however there are two problems with this approach: |
| 8 | +
|
| 9 | +1. Some options (e.g. postcss, compilerModules) may contain non-serializable |
| 10 | + values and cannot be passed via inline requests |
| 11 | +2. Passing everything via inline requests makes the module string extremely |
| 12 | + verbose, and can be quite annoying in error messages. |
| 13 | +
|
| 14 | +To get around this, we cache the options in this module here in order to share |
| 15 | +it between loaders. |
| 16 | +
|
| 17 | +- In order to support multiple uses of vue-loader with different options, |
| 18 | +each options object is cached with an id. |
| 19 | +- To share options across threads in threadMode, options are serialized and |
| 20 | +cached on disk. |
| 21 | +*/ |
| 22 | + |
| 23 | +const fs = require('fs') |
| 24 | +const path = require('path') |
| 25 | +const hash = require('hash-sum') |
| 26 | + |
| 27 | +const optionsToId = new Map() |
| 28 | +const idToOptions = new Map() |
| 29 | + |
| 30 | +exports.saveOptions = options => { |
| 31 | + if (optionsToId.has(options)) { |
| 32 | + return optionsToId.get(options) |
| 33 | + } |
| 34 | + |
| 35 | + const threadMode = options.threadMode |
| 36 | + const serialized = threadMode ? serialize(options) : null |
| 37 | + const id = serialized ? hash(serialized) : String(idToOptions.size) |
| 38 | + |
| 39 | + idToOptions.set(id, options) |
| 40 | + optionsToId.set(options, id) |
| 41 | + |
| 42 | + if (serialized) { |
| 43 | + const fsidToOptionsPath = getidToOptionsPath(id) |
| 44 | + if (!fs.existsSync(fsidToOptionsPath)) { |
| 45 | + fs.writeFileSync(fsidToOptionsPath, serialized) |
| 46 | + } |
| 47 | + } |
| 48 | + |
| 49 | + return id |
| 50 | +} |
| 51 | + |
| 52 | +exports.loadOptions = id => { |
| 53 | + const res = idToOptions.get(id) |
| 54 | + if (res) { |
| 55 | + return res |
| 56 | + } |
| 57 | + const fsidToOptionsPath = getidToOptionsPath(id) |
| 58 | + if (fs.existsSync(fsidToOptionsPath)) { |
| 59 | + return JSON.parse(fs.readFileSync(fsidToOptionsPath, 'utf-8')) |
| 60 | + } else { |
| 61 | + return {} |
| 62 | + } |
| 63 | +} |
| 64 | + |
| 65 | +function serialize (options) { |
| 66 | + let res |
| 67 | + try { |
| 68 | + res = JSON.stringify(options) |
| 69 | + } catch (e) { |
| 70 | + throw new Error(`options must be JSON serializable in thread mode.`) |
| 71 | + } |
| 72 | + return res |
| 73 | +} |
| 74 | + |
| 75 | +function getidToOptionsPath (id) { |
| 76 | + return path.resolve(__dirname, `.options-idToOptions-${id}`) |
| 77 | +} |
0 commit comments