-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathindex.js
121 lines (114 loc) · 3.22 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
'use strict'
var vm = require('vm')
var MemoryFileSystem = require('memory-fs')
var createRoutes = require('react-router').createRoutes
var webpack = require('webpack')
function compileRoutes (config) {
return new Promise(function (resolve, reject) {
var compiler = webpack(config)
var fs = compiler.outputFileSystem = new MemoryFileSystem()
compiler.run(function (err, stats) {
if (err) { return reject(err) }
resolve(fs)
})
})
}
function executeRoutes (fs) {
return new Promise(function (resolve, reject) {
try {
var source = fs.readFileSync('/routes.js').toString()
var script = new vm.Script(source, { filename: 'routes.vm' })
var context = {}
var routes = script.runInNewContext(context).routes
resolve(routes)
} catch (err) {
reject(err)
}
})
}
function flattenRoutes (routes, base, paths) {
return routes.reduce(function (paths, route) {
var path = route.path === '*' ? route.staticName || 'nomatch' : route.path
path = /^\//.test(path) ? path : base + path
if (!route.staticExclude) { paths.push(path) }
if (route.childRoutes) {
var nextBase = /\/$/.test(path) ? path : path + '/'
paths = flattenRoutes(route.childRoutes, nextBase, paths)
}
return paths
}, paths || [])
}
function ReactRouterPathExtractorWebpackPlugin (routesFile, options, plugins) {
var args = Array.prototype.splice.call(arguments, 0, 3)
switch (args.length) {
case 3:
this.routesFile = args[0]
this.options = args[1]
this.plugins = args[2]
break
case 2:
if (args[0] && typeof args[0] === 'object') {
this.options = args[0]
this.plugins = args[1]
this.routesFile = this.options.routesFile
} else {
this.routesFile = args[0]
this.plugins = args[1]
this.options = {}
}
break
default:
throw Error('Invalid arguments')
}
if (!this.routesFile) {
throw new Error('A routesFile is required')
}
if (typeof this.routesFile !== 'string') {
throw new Error('The routesFile must be a string')
}
if (typeof this.options !== 'object') {
throw new Error('Options must be an object')
}
if (typeof this.plugins !== 'function') {
throw new Error('Callback must be a function')
}
}
ReactRouterPathExtractorWebpackPlugin.prototype.apply = function (compiler) {
var self = this
compiler.plugin('make', function (compilation, callback) {
compileRoutes({
context: compiler.context,
entry: {
routes: [self.routesFile]
},
output: {
path: '/',
filename: 'routes.js'
},
module: {
loaders: compiler.options.module.loaders
}
})
.catch(callback)
.then(executeRoutes)
.catch(callback)
.then(function (routes) {
try {
return createRoutes(routes)
} catch (err) {
throw err
}
})
.catch(callback)
.then(function (routes) {
var paths = flattenRoutes(routes)
if (typeof self.plugins === 'function') {
self.plugins(paths, routes).forEach(function (plugin) {
plugin.apply(compiler)
})
callback(null, routes)
}
})
})
}
module.exports = ReactRouterPathExtractorWebpackPlugin