UNPKG

6.76 kBJavaScriptView Raw
1/*
2* @Author: gbk <ck0123456@gmail.com>
3* @Date: 2016-04-21 17:34:00
4* @Last Modified by: gbk
5* @Last Modified time: 2016-06-14 15:42:03
6*/
7
8'use strict';
9
10var fs = require('fs');
11var os = require('os');
12var spawn = require('child_process').spawn;
13
14var webpack = require('webpack');
15var UglifyJs = require('uglify-js');
16var CleanCss = require('clean-css');
17
18var pkg = require('../package.json');
19var util = require('./util');
20
21// plugin defination
22module.exports = {
23
24 description: pkg.description,
25
26 options: [
27 [ '-s, --src <dir>', 'source directory, default to `src`', 'src' ],
28 [ '-d, --dist <dir>', 'build directory, default to `dist`', 'dist' ],
29 [ '-o, --loose', 'use babel es2015 loose mode to transform codes' ],
30 [ '-c, --keepconsole', 'keep `console.log`' ],
31 [ ' --skipminify', 'skip minify js and css' ],
32 [ '-p, --progress', 'show progress' ],
33 [ '-l, --libraries', 'libraries builder config' ],
34 [ ' --skipinstall', 'skip npm install' ],
35 [ '-n, --npm [npm]', 'which npm to use(like npm|cnpm|tnpm)', 'npm' ]
36 ],
37
38 action: function(options) {
39
40 // options
41 var src = options.src;
42 var dist = options.dist;
43 var loose = options.loose;
44 var keepconsole = options.keepconsole;
45 var skipminify = options.skipminify;
46 var progress = options.progress;
47 var libraries = options.libraries;
48 var skipinstall = options.skipinstall;
49 var npm = options.npm;
50
51 // libraries is required
52 if (!libraries) {
53 console.error('No `libraries` config found in `abc.json`');
54 return;
55 }
56
57 // enable es2015 loose mode
58 if (loose) {
59
60 // modify es2015 presets, add `loose: true` option
61 var es2015Plugins = require(util.babel('preset', 'es2015')).plugins;
62 for (var i = 0; i < es2015Plugins.length; i++) {
63 if (Array.isArray(es2015Plugins[i])) {
64 es2015Plugins[i][1].loose = true;
65 } else {
66 es2015Plugins[i] = [
67 es2015Plugins[i],
68 { loose: true }
69 ];
70 }
71 }
72 }
73
74 // parse rules and generate entry
75 var entries = {};
76 var command = [];
77 var hasEntry = false;
78 for (var key in libraries) {
79 var lib = libraries[key];
80 var name = lib.output.replace(/\.js$/, '');
81 var srcFile = entries[name] = './lib__' + name + '.js';
82 var srcContent = [ 'window["' + key + '"]={' ];
83 for (var comp in lib.mappings) {
84 var dep = lib.mappings[comp];
85 command.push(dep);
86 if (/^@ali\//.test(dep)) {
87 dep = dep.split('@').slice(0, 2).join('@');
88 } else {
89 dep = dep.split('@')[0];
90 }
91 srcContent.push('"' + comp + '":require("' + dep + '"),');
92 }
93 srcContent.push('};');
94 fs.writeFileSync(srcFile, srcContent.join('\n'));
95 hasEntry = true;
96 }
97 if (!hasEntry) {
98 return;
99 }
100
101 // install deps
102 console.log('Installing dependencies of libraries...');
103 spawn(process.platform === 'win32' ? npm + '.cmd' : npm, skipinstall ? [ '-v' ] : [
104 'install',
105 '-d'
106 ].concat(command), {
107 stdio: 'inherit',
108 stderr: 'inherit'
109 }).on('exit', function(code) {
110 if (code !== 0) {
111 console.error('install error');
112 }
113
114 // build libraries
115 console.log('Building libraries...');
116 webpack({
117 entry: entries,
118 output: {
119 path: util.cwdPath(dist),
120 filename: '[name].js'
121 },
122 plugins: [
123 new webpack.SourceMapDevToolPlugin({
124 columns: false
125 }),
126 new webpack.optimize.DedupePlugin()
127 ],
128 resolveLoader: {
129 modulesDirectories: [
130 util.relPath('..', 'node_modules'),
131 'node_modules'
132 ]
133 },
134 externals: {
135 'react': 'window.React',
136 'react-dom': 'window.ReactDOM || window.React'
137 },
138 module: {
139 loaders: [
140 {
141 test: /\.jsx?$/,
142 loader: 'babel',
143 exclude: function (path) { // only uxcore and tingle need transform code
144 var isNpmModule = !!path.match(/node_modules/);
145 var isLib = !!path.match(/node_modules[\/\\](@ali[\/\\])?tingle/);
146 return isNpmModule && !isLib;
147 },
148 query: {
149 plugins: util.babel('plugin', [
150 'add-module-exports',
151 'transform-es3-member-expression-literals',
152 'transform-es3-property-literals'
153 ]),
154 presets: util.babel('preset', [
155 'es2015',
156 'stage-0',
157 'react'
158 ]),
159 cacheDirectory: os.tmpdir()
160 }
161 }
162 ]
163 }
164 }, function(err, stats) {
165 if(err) {
166 console.error(err);
167 }
168
169 // clean
170 for (var key in entries) {
171 try {
172 fs.unlinkSync(entries[key]);
173 } catch (e) {
174 }
175 }
176
177 console.log(stats.toString({
178 version: false,
179 hash: false,
180 chunks: false,
181 children: false
182 }));
183 stats.toJson({
184 hash: false,
185 chunks: false,
186 children: false,
187 modules: false
188 }).assets.forEach(function(n) {
189
190 // minify
191 var file = util.cwdPath(dist, n.name);
192 var minFile = file.replace(/.js$/, '.min.js').replace(/.css$/, '.min.css');
193 if (/\.js$/.test(file)) {
194 console.log('Minify file: ' + file);
195 var result = UglifyJs.minify(file, {
196 compress: {
197 warnings: false,
198 drop_console: !keepconsole
199 },
200 comments: false
201 });
202 fs.writeFileSync(minFile, result.code);
203 } else if (/\.css$/.test(file)) {
204 console.log('Minify file: ' + file);
205 var result = new CleanCss({
206 keepSpecialComments: 0,
207 compatibility: true,
208 advanced: false,
209 processImport: true
210 }).minify(fs.readFileSync(file, 'utf-8'));
211 fs.writeFileSync(minFile, result.styles);
212 }
213
214 // copy to lib dir
215 try {
216 fs.mkdirSync(util.cwdPath(src, 'lib'));
217 } catch (e) {
218 }
219 try {
220 var libFile = util.cwdPath(src, 'lib', n.name);
221 var libMinFile = libFile.replace(/.js$/, '.min.js').replace(/.css$/, '.min.css');
222 fs.writeFileSync(libFile, fs.readFileSync(file));
223 fs.writeFileSync(libMinFile, fs.readFileSync(minFile));
224 } catch (e) {
225 }
226 });
227 });
228 });
229 }
230};