UNPKG

6.36 kBJavaScriptView Raw
1'use strict'
2
3var fs = require('fs')
4var path = require('path')
5
6var browserify = require('browserify')
7var through = require('through2')
8var Promise = require('bluebird')
9var babelify = require('babelify')
10var xtend = require('xtend')
11var bpack = require('browser-pack')
12var envify = require('envify/custom')
13var uglifyify = require('uglifyify')
14
15var qasSrc = fs.readFileSync(require.resolve('qas/qas.min.js'), 'utf-8')
16var qasWrapperHeader = fs.readFileSync(require.resolve('qas/loader-wrapper-header.js'), 'utf-8')
17var qasWrapperFooter = fs.readFileSync(require.resolve('qas/loader-wrapper-footer.js'), 'utf-8')
18
19var APP_ROOT = global.APP_ROOT || process.cwd()
20var pkginfo = require(path.join(APP_ROOT, 'package.json'))
21var pkgBabelify
22if (pkginfo.browserify && pkginfo.browserify.transform && pkginfo.browserify.transform.length) {
23 if (pkginfo.browserify.transform.filter(t => t[0] === 'babelify').length) {
24 pkgBabelify = true
25 }
26}
27var reactBeUsed
28if ((pkginfo.dependencies || {})['react'] || (pkginfo.devDependencies || {})['react']) {
29 reactBeUsed = true
30}
31var vueBeUsed = (function () {
32 var m, version
33 if ( (version = (pkginfo.dependencies || {})['vue'] || (pkginfo.devDependencies || {})['vue']) ) {
34 if ( !(m = /\d/.exec(version)) ) {
35 return false
36 }
37 if (m[0] === '1' || m[0] === '2') {
38 return m[0]
39 }
40 }
41 return false
42}())
43
44var env = process.env.NODE_ENV || 'development'
45var isDev = env === 'development'
46
47var args = {
48 debug: isDev,
49 basedir: APP_ROOT,
50 paths: ['.'],
51 cache: {},
52 packageCache: {},
53 extensions: ['jsx']
54}
55function useBabelRc () {
56 var babelRcPath = path.resolve(process.cwd(), '.babelrc')
57 if (!fs.existsSync(babelRcPath)) {
58 return false
59 }
60 var rc
61 try {
62 rc = JSON.parse(fs.readFileSync(babelRcPath, 'utf-8'))
63 } catch (e) {
64 throw new Error('[vueify] Your .babelrc seems to be incorrectly formatted.')
65 }
66 return !!rc
67}
68
69var bundle = function (entries, requires, opts) {
70 opts = opts || {}
71 var bopts = xtend(args, opts.args || {})
72 var babelifyOpts
73 if (opts.babelify !== false && !pkgBabelify) {
74 babelifyOpts = xtend({}, opts.babelify)
75 if (!babelifyOpts.presets || (Array.isArray(babelifyOpts.presets) && !babelifyOpts.presets.length)) {
76 babelifyOpts.presets = [require('babel-preset-dysonshell')]
77 if (reactBeUsed) {
78 babelifyOpts.presets.push(require('babel-preset-react'))
79 if (opts.hmr) {
80 babelifyOpts.presets.push(require('babel-preset-react-hmre'))
81 }
82 }
83 }
84 if (!babelifyOpts.ignore || (Array.isArray(babelifyOpts.ignore) && !babelifyOpts.ignore.length)) {
85 babelifyOpts.ignore = /[\\\/]node_modules[\\\/]/
86 }
87 }
88 if (vueBeUsed) {
89 var vueify
90 babelifyOpts.presets = babelifyOpts.presets || []
91 babelifyOpts.plugins = babelifyOpts.plugins || []
92 babelifyOpts.plugins.push(require('babel-plugin-transform-runtime'))
93 if (vueBeUsed === '1') {
94 if (!useBabelRc()) { // TODO: babelify vs .babelrc?
95 require('vue1ify/node_modules/vueify/lib/compilers/options').babel = {
96 presets: babelifyOpts.presets.slice(),
97 plugins: babelifyOpts.plugins.slice()
98 }
99 }
100 bopts.paths = path.join(path.dirname(require.resolve('vue1ify')), 'node_modules', 'vueify', 'node_modules') + (process.platform === 'win32' ? ';' : ':') + path.join(path.dirname(require.resolve('vue1ify')), 'node_modules') + (process.platform === 'win32' ? ';' : ':') + (opts.paths || process.env.NODE_PATH || '')
101 vueify = require('vue1ify')
102 } else {
103 vueify = [require('vue2ify'), {
104 babel: {
105 presets: babelifyOpts.presets.slice(),
106 plugins: babelifyOpts.plugins.slice()
107 }
108 }]
109 bopts.paths = path.join(path.dirname(require.resolve('vue2ify')), 'node_modules') + (process.platform === 'win32' ? ';' : ':') + (opts.paths || process.env.NODE_PATH || '')
110 }
111 }
112 var b = browserify(bopts)
113 if (opts.args.packageCache) {
114 b.on('package', function (pkg) {
115 var file = path.join(pkg.__dirname, 'package.json')
116 opts.args.packageCache[file] = pkg
117 })
118 }
119 b = alterPipeline(b, opts)
120 if (typeof opts.alterb === 'function') {
121 opts.alterb(b)
122 }
123 if (entries && entries.length) {
124 entries.forEach(fullPath => b.add(fullPath))
125 }
126 if (requires && requires.length) {
127 requires.forEach(fullPath => b.require(fullPath))
128 }
129 if (babelifyOpts) {
130 b.transform(babelify, babelifyOpts)
131 }
132 if (vueify) {
133 b.transform(vueify)
134 }
135 if (opts.envify !== false) {
136 b.transform(envify(opts.envify || {
137 _: 'purge',
138 NODE_ENV: env
139 }))
140 }
141 if (opts.transforms) {
142 b.transform(opts.transforms)
143 }
144 if (opts.uglifyify !== false && !isDev) {
145 b.transform(uglifyify, {exts: ['.js', '.jsx']})
146 }
147 if (opts.externals && !opts.global) {
148 if (opts.externals) {
149 b.external(opts.externals)
150 }
151 }
152 return bundlePromise(b).then(src => {
153 if (opts.global) {
154 return new Buffer(qasSrc + 'QAS.sync(function () { ' + src + '}); QAS.ready()', 'utf-8')
155 } else {
156 return new Buffer(qasWrapperHeader + src + qasWrapperFooter + 'if (!document.querySelector("script[brocode-global]")) { ' + qasSrc + 'QAS.ready() };', 'utf-8')
157 }
158 }).catch(err => {
159 if (err._babel) {
160 console.error(err.message);
161 console.error(err.codeFrame);
162 }
163 throw err
164 })
165}
166
167function alterPipeline (b, opts) {
168 opts = opts || {}
169 if (b.pipeline.get('dedupe') && b.pipeline.get('dedupe').length) {
170 b.pipeline.get('dedupe').splice(0, 1) // arguments[4] bug
171 }
172 b.pipeline.get('pack')
173 .splice(0, 1, bpack(xtend(args, {
174 raw: true,
175 hasExports: true,
176 externalRequireName: 'var require = QAS.require; QAS.require'
177 })))
178 if (opts.args.cache) {
179 var cache = opts.args.cache
180 b.pipeline.get('deps').push(through.obj(function (row, enc, next) {
181 var file = row.expose ? b._expose[row.id] : row.file
182 cache[file] = {
183 source: row.source,
184 deps: xtend(row.deps)
185 }
186 this.push(row)
187 next()
188 }))
189 }
190 return b
191}
192
193function bundlePromise (b) { // because b.bundle checks arity :(
194 return new Promise(function (resolve, reject) {
195 return b.bundle(function (err, src) {
196 if (err) {
197 return reject(err)
198 }
199 resolve(src)
200 })
201 })
202}
203
204module.exports = bundle