1 | var debug = require('debug')('bankai.node-script')
|
2 | var concat = require('concat-stream')
|
3 | var exorcist = require('exorcist')
|
4 | var tfilter = require('tfilter')
|
5 | var assert = require('assert')
|
6 |
|
7 | var babelPresetEnv = require('babel-preset-env')
|
8 | var splitRequire = require('split-require')
|
9 | var browserslist = require('browserslist')
|
10 | var cssExtract = require('css-extract')
|
11 | var browserify = require('browserify')
|
12 | var babelify = require('babelify')
|
13 | var watchify = require('watchify')
|
14 | var sheetify = require('sheetify')
|
15 | var yoyoify = require('yo-yoify')
|
16 | var tinyify = require('tinyify')
|
17 | var glslify = require('glslify')
|
18 | var envify = require('envify/custom')
|
19 | var brfs = require('brfs')
|
20 |
|
21 | var ttyError = require('./tty-error')
|
22 | var exorcise = require('./exorcise')
|
23 |
|
24 | var defaultBrowsers = [
|
25 | 'last 2 Chrome versions',
|
26 | 'last 2 Firefox versions',
|
27 | 'last 2 Safari versions',
|
28 | 'last 2 Edge versions',
|
29 | '> 1%'
|
30 | ]
|
31 |
|
32 | module.exports = node
|
33 |
|
34 | function node (state, createEdge) {
|
35 | assert.equal(typeof state.metadata.entry, 'string', 'state.metadata.entries should be type string')
|
36 |
|
37 | this.emit('progress', 'scripts', 0)
|
38 |
|
39 | var self = this
|
40 | var entry = state.metadata.entry
|
41 | var fullPaths = Boolean(state.metadata.fullPaths)
|
42 | var b = browserify(browserifyOpts([entry], fullPaths))
|
43 | var shouldMinify = !state.metadata.watch
|
44 |
|
45 |
|
46 | var browsers = browserslist(null, { path: entry })
|
47 | if (!browsers.length) browsers = defaultBrowsers
|
48 |
|
49 | var babelPresets = [
|
50 | [babelPresetEnv, {
|
51 | targets: { browsers: browsers }
|
52 | }]
|
53 | ]
|
54 |
|
55 | if (state.metadata.watch) {
|
56 | b = watchify(b)
|
57 | debug('watching ' + entry)
|
58 | this.on('close', function () {
|
59 | debug('closing file watcher')
|
60 | b.close()
|
61 | })
|
62 | }
|
63 |
|
64 | b.ignore('sheetify/insert')
|
65 | b.transform(sheetify)
|
66 | b.transform(glslify)
|
67 |
|
68 | b.transform(tfilter(babelify, { include: /node_modules/ }), {
|
69 | global: true,
|
70 | babelrc: false,
|
71 | presets: babelPresets
|
72 | })
|
73 |
|
74 | b.transform(tfilter(babelify, { exclude: /node_modules/ }), {
|
75 | global: true,
|
76 | babelrc: true,
|
77 | presets: babelPresets
|
78 | })
|
79 | b.transform(brfs, { global: true })
|
80 | b.transform(yoyoify, { global: true })
|
81 |
|
82 | if (!fullPaths) b.plugin(cssExtract, { out: bundleStyles })
|
83 |
|
84 |
|
85 |
|
86 |
|
87 | if (!fullPaths) {
|
88 | b.plugin(splitRequire, {
|
89 | filename: function (record) {
|
90 | return 'bundle-' + record.index + '.js'
|
91 | },
|
92 | output: bundleDynamicBundle,
|
93 | sri: 'sha512'
|
94 | })
|
95 |
|
96 |
|
97 | b.on('split.pipeline', function (pipeline, entry, name) {
|
98 | pipeline.get('wrap').push(exorciseDynamicBundle(name))
|
99 | })
|
100 | }
|
101 |
|
102 | if (shouldMinify) {
|
103 | b.plugin(tinyify)
|
104 | b.on('split.pipeline', function (pipeline) {
|
105 | tinyify.applyToPipeline(pipeline, b._options)
|
106 | })
|
107 | } else {
|
108 | var env = Object.assign({
|
109 | NODE_ENV: 'development'
|
110 | }, process.env)
|
111 | b.transform(envify(env), { global: true })
|
112 | }
|
113 |
|
114 | bundleScripts()
|
115 | b.on('update', bundleScripts)
|
116 |
|
117 | var dynamicBundles
|
118 | function bundleScripts (files) {
|
119 | if (files) debug('triggering update because of changes in', files)
|
120 | self.emit('progress', 'scripts', 30)
|
121 |
|
122 | dynamicBundles = []
|
123 | b.bundle(function (err, bundle) {
|
124 | if (err) {
|
125 | delete err.stream
|
126 | err = ttyError('scripts', 'browserify.bundle', err)
|
127 | return self.emit('error', 'scripts', 'browserify.bundle', err)
|
128 | }
|
129 | var mapName = 'bundle.js.map'
|
130 | exorcise(bundle, mapName, function (err, bundle, map) {
|
131 | if (err) return self.emit('error', 'scripts', 'exorcise', err)
|
132 | createEdge(mapName, Buffer.from(map), {
|
133 | mime: 'application/json'
|
134 | })
|
135 | createEdge('bundle', bundle, {
|
136 | mime: 'application/javascript',
|
137 | dynamicBundles: dynamicBundles
|
138 | })
|
139 | self.emit('progress', 'scripts', 100)
|
140 | })
|
141 | })
|
142 | }
|
143 |
|
144 | function exorciseDynamicBundle (bundleName) {
|
145 | var mapName = bundleName + '.map'
|
146 | return exorcist(concat({ encoding: 'buffer' }, function (map) {
|
147 | createEdge(mapName, map, {
|
148 | mime: 'application/json'
|
149 | })
|
150 | }), mapName)
|
151 | }
|
152 |
|
153 | function bundleDynamicBundle (bundleName) {
|
154 | var edgeName = bundleName.replace(/\.js$/, '')
|
155 | var stream = concat({ encoding: 'buffer' }, function (bundle) {
|
156 | dynamicBundles.push(bundleName)
|
157 | createEdge(edgeName, bundle, {
|
158 | mime: 'application/javascript'
|
159 | })
|
160 |
|
161 |
|
162 | stream.emit('name', state.scripts[edgeName].hash.toString('hex').slice(0, 16) + '/' + bundleName)
|
163 | })
|
164 | return stream
|
165 | }
|
166 |
|
167 | function bundleStyles () {
|
168 | return concat({ encoding: 'buffer' }, function (buf) {
|
169 | createEdge('style', buf, {
|
170 | mime: 'text/css'
|
171 | })
|
172 | })
|
173 | }
|
174 | }
|
175 |
|
176 | function browserifyOpts (entries, fullPaths) {
|
177 | assert.ok(Array.isArray(entries), 'browserifyOpts: entries should be an array')
|
178 | return {
|
179 | debug: true,
|
180 | fullPaths: fullPaths,
|
181 | entries: entries,
|
182 | packageCache: {},
|
183 | cache: {}
|
184 | }
|
185 | }
|