UNPKG

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