1 | const browserify = require('browserify');
|
2 | const fse = require('fs-extra');
|
3 | const path = require('path');
|
4 | const watchify = require('watchify');
|
5 | const sourceMaps = require('source-map-support');
|
6 | const livereload = require('livereload');
|
7 |
|
8 | const utils = require('./lib/utils.js');
|
9 | const transform = require('./lib/transforms');
|
10 | const codeTransform = require('./lib/transforms/code.js');
|
11 | const renderer = require('./lib/renderer.js');
|
12 | const getOpts = require('./lib/getopts.js');
|
13 | const log = require('./lib/utils/log.js');
|
14 | const Less = require('./lib/utils/less.js');
|
15 |
|
16 |
|
17 | const startApp = async (opts)=>{
|
18 | if(!opts.app){
|
19 | console.log(`A server app was not specified, dev server will not run. Set 'main' in your package.json to enable this.`);
|
20 | return;
|
21 | }
|
22 | const nodemon = require('nodemon');
|
23 | return new Promise((resolve, reject)=>{
|
24 | let deps = [];
|
25 | browserify({ require : opts.app, bundleExternal : false,
|
26 | postFilter : (id, filepath, pkg)=>{
|
27 | if(id.indexOf(opts.paths.build) !== -1) return false;
|
28 |
|
29 | deps.push(filepath);
|
30 | return true;
|
31 | }
|
32 | })
|
33 | .transform((file)=>transform(file, opts, [codeTransform]), {global : true})
|
34 | .bundle((err)=>err?reject(err):resolve(deps));
|
35 | })
|
36 | .then((appDeps)=>{
|
37 | return nodemon({ script:opts.app, watch:appDeps, delay:2 })
|
38 | .on('restart', (files)=>log.restartServer(opts.app, files));
|
39 | })
|
40 | };
|
41 |
|
42 | const devEntryPoint = async (entryPoint, Opts)=>{
|
43 | let opts = Object.assign({
|
44 | entry : {
|
45 | name : path.basename(entryPoint).split('.')[0],
|
46 | dir : path.dirname(entryPoint)
|
47 | }
|
48 | }, Opts);
|
49 |
|
50 | if(!fse.pathExistsSync(path.resolve(process.cwd(), opts.paths.build, opts.entry.name))){
|
51 | throw log.notBuilt(opts.entry);
|
52 | }
|
53 |
|
54 | const bundler = browserify({
|
55 | cache : {},
|
56 | packageCache : {},
|
57 | debug : true,
|
58 | standalone : opts.entry.name,
|
59 | paths : opts.shared,
|
60 | plugin : [watchify],
|
61 | ignoreMissing : true,
|
62 | postFilter : (id, filepath, pkg)=>{
|
63 | return utils.shouldBundle(filepath, id, opts);
|
64 | },
|
65 | })
|
66 | .require(entryPoint)
|
67 | .transform((file)=>transform(file, opts), {global : true})
|
68 | .on('update', (files)=>{
|
69 | log.rebundle(opts.entry, files);
|
70 | bundle();
|
71 | });
|
72 |
|
73 | let lastBundle;
|
74 | const bundle = async ()=>{
|
75 | const logEnd = log.buildEntryPoint(opts.entry);
|
76 | await utils.bundle(bundler).then((code)=>{
|
77 | if(lastBundle != code) fse.writeFileSync(paths.code, code);
|
78 | lastBundle = code;
|
79 | });
|
80 | await Less.compile(opts).then((css)=>fse.writeFile(paths.style, css));
|
81 | logEnd();
|
82 | };
|
83 |
|
84 | const paths = utils.paths(opts.paths, opts.entry.name);
|
85 | await renderer(Object.assign(opts, {dev : true}));
|
86 | await bundle();
|
87 | };
|
88 |
|
89 | const setupLiveReload = (opts)=>{
|
90 | const lr = livereload.createServer();
|
91 | lr.server.on('error', (err)=>{
|
92 | if(err.code == 'EADDRINUSE'){
|
93 | console.log('ERR: Could not setup LiveReload conection. This is because another instance of Vitreum Dev is running.');
|
94 | }else{
|
95 | throw err;
|
96 | }
|
97 | })
|
98 | lr.watch(opts.paths.build);
|
99 | };
|
100 |
|
101 | module.exports = async (entryPoints, opts)=>{
|
102 | opts = getOpts(opts, entryPoints);
|
103 | log.beginDev(opts);
|
104 | sourceMaps.install();
|
105 | await opts.targets.reduce((flow, ep)=>flow.then(()=>devEntryPoint(ep, opts)), Promise.resolve());
|
106 | setupLiveReload(opts);
|
107 | return await startApp(opts);
|
108 | };
|