1 | #!/usr/bin/env node
|
2 |
|
3 | var fs = require("fs");
|
4 | var path = require("path");
|
5 | var program = require("commander")
|
6 |
|
7 | var libdir = path.dirname(process.argv[1]);
|
8 | var libmod = libdir + (fs.existsSync(libdir + "/node_modules/webpack") ? "/node_modules" : "/..");
|
9 | var command = process.argv[2];
|
10 | var context = process.argv[3] && path.resolve(process.argv[3]);
|
11 |
|
12 |
|
13 | var version = JSON.parse(fs.readFileSync(libdir + "/package.json")).version;
|
14 | console.log("Version: react-beaker " + version + "\n");
|
15 | program
|
16 | .version(version)
|
17 | .option("-c, --tsconfig [path]", "set tsconfig.json file path")
|
18 | .option("-p, --publicPath [path]", "set publicPath option")
|
19 | .option("-t, --reactToolkit", "build react-toolkit")
|
20 | .option("-h, --hash", "include chunkhash in output filename")
|
21 | .option("-s, --strict", "Set TypeScript strict flag to true")
|
22 | .parse(process.argv);
|
23 |
|
24 |
|
25 | if (!command || !context || ["watch", "build", "publish"].indexOf(command) < 0) {
|
26 | help();
|
27 | process.exit(1);
|
28 | }
|
29 |
|
30 |
|
31 | var entry = {};
|
32 | var entriesDir = context + "/js/entries/";
|
33 | fs.readdirSync(entriesDir).forEach(function(filename) {
|
34 | if (/.*\.sw.$/.test(filename) === false) {
|
35 | entry[filename.replace(/\.[^\.]+$/, "")] = entriesDir + filename;
|
36 | }
|
37 | });
|
38 |
|
39 |
|
40 | try {
|
41 | var pages = fs.readdirSync(context + "/html").filter(function(filename) {
|
42 | return /.*\.sw.$/.test(filename) === false;
|
43 | });
|
44 | } catch (_) {
|
45 | var pages = [];
|
46 | }
|
47 |
|
48 |
|
49 | var options = {};
|
50 | switch (command) {
|
51 | case "watch":
|
52 | options = {
|
53 | "NODE_ENV": '"development"',
|
54 | "filename": "[name].min.js",
|
55 | "minimize": false,
|
56 | "sourceMap": true,
|
57 | };
|
58 | break;
|
59 | case "build":
|
60 | options = {
|
61 | "NODE_ENV": '"production"',
|
62 | "filename": "[name].js",
|
63 | "minimize": false,
|
64 | "sourceMap": false,
|
65 | };
|
66 | break;
|
67 | case "publish":
|
68 | options = {
|
69 | "NODE_ENV": '"production"',
|
70 | "filename": program.hash ? "[name].[chunkhash].min.js" : "[name].min.js",
|
71 | "minimize": true,
|
72 | "sourceMap": false,
|
73 | };
|
74 | break;
|
75 | }
|
76 |
|
77 |
|
78 | var tsconfig = {
|
79 | compilerOptions: {
|
80 | "jsx": "react",
|
81 | "module": "es2015",
|
82 | "allowSyntheticDefaultImports": true,
|
83 | "moduleResolution": "node",
|
84 | "strict": program.strict,
|
85 | "target": "es5",
|
86 | "lib": ["dom", "es2017"],
|
87 | "experimentalDecorators": true,
|
88 | }
|
89 | }
|
90 | var tsconfigFile = program.tsconfig && path.resolve(program.tsconfig)
|
91 | if (!tsconfig || !fs.existsSync(tsconfigFile)) {
|
92 | fs.writeFileSync(context + "/tsconfig.json", JSON.stringify(tsconfig, null, 2))
|
93 | }
|
94 |
|
95 | var webpack = require(libmod + "/webpack");
|
96 | var HtmlWebpackPlugin = require(libmod + "/html-webpack-plugin");
|
97 | var autoprefixer = require(libmod + "/autoprefixer");
|
98 | var loadersForCSSFile = [
|
99 | {
|
100 | loader: "style-loader"
|
101 | },
|
102 | {
|
103 | loader: "css-loader",
|
104 | options: {
|
105 | minimize: true
|
106 | }
|
107 | },
|
108 | {
|
109 | loader: "postcss-loader",
|
110 | options: {
|
111 | plugins: function() {
|
112 | return [
|
113 | autoprefixer({
|
114 | browsers: ["last 2 versions", "Safari >= 8"]
|
115 | })
|
116 | ];
|
117 | }
|
118 | }
|
119 | }
|
120 | ]
|
121 |
|
122 | var compiler = webpack({
|
123 | devtool: options.sourceMap && "inline-source-map",
|
124 | context: context,
|
125 | resolve: {
|
126 | extensions: [".web.js", ".js", ".jsx", ".ts", ".tsx"],
|
127 | alias: {
|
128 | "react/lib": libmod + "/react/lib",
|
129 | }
|
130 | },
|
131 | externals: {
|
132 | "react": "React",
|
133 | "redux": "Redux",
|
134 | "react-dom": "ReactDOM",
|
135 | "react-router": "ReactRouter",
|
136 | "react-addons-css-transition-group": "ReactCSSTransitionGroup",
|
137 | },
|
138 | resolveLoader: {
|
139 | modules: [libmod]
|
140 | },
|
141 | entry: entry,
|
142 | output: {
|
143 | path: context + "/dist",
|
144 | filename: options.filename,
|
145 | publicPath: program.publicPath || ""
|
146 | },
|
147 | module: {
|
148 | rules: [
|
149 | {
|
150 | test: /\.jsx?$/,
|
151 | loader: "babel-loader",
|
152 | exclude: /node_modules/,
|
153 | query: {
|
154 | presets: [
|
155 | libmod + "/babel-preset-react",
|
156 | libmod + "/babel-preset-es2015",
|
157 | ],
|
158 | plugins: [
|
159 | libmod + "/babel-plugin-transform-object-assign",
|
160 | ],
|
161 | },
|
162 | },
|
163 | {
|
164 | test: /\.tsx?$/,
|
165 | loader: "ts-loader",
|
166 | exclude: /node_modules/
|
167 | },
|
168 | {
|
169 | test: /^[^!]+.css$/,
|
170 | use: loadersForCSSFile
|
171 | },
|
172 | {
|
173 | test: /^[^!]+.less$/,
|
174 | use: loadersForCSSFile.concat(
|
175 | {
|
176 | loader: "less-loader"
|
177 | }
|
178 | )
|
179 | },
|
180 |
|
181 | |
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 | ],
|
188 | },
|
189 | plugins: pages.map(function(filename) {
|
190 | return new HtmlWebpackPlugin({
|
191 | filename: filename,
|
192 | template: context + "/html/" + filename,
|
193 | });
|
194 | }).concat(options.minimize ? [
|
195 | new webpack.optimize.UglifyJsPlugin({
|
196 | sourceMap: true,
|
197 | compress: {
|
198 | warnings: false
|
199 | }
|
200 | }),
|
201 | new webpack.LoaderOptionsPlugin({
|
202 | minimize: true
|
203 | })
|
204 | ] : []).concat([
|
205 | new webpack.DefinePlugin({
|
206 | "process.env": {
|
207 | NODE_ENV: options.NODE_ENV
|
208 | }
|
209 | })
|
210 | ]),
|
211 | stats: "errors-only",
|
212 | });
|
213 |
|
214 | function buildReactCore() {
|
215 | if (!program.reactToolkit) return
|
216 | webpack({
|
217 | context: libdir,
|
218 | entry: libdir + "/react-toolkit.js",
|
219 | output: {
|
220 | path: context + "/dist",
|
221 | filename: "react-toolkit.min.js",
|
222 | },
|
223 | plugins: [
|
224 | new webpack.optimize.UglifyJsPlugin({
|
225 | minimize: true
|
226 | }),
|
227 | new webpack.DefinePlugin({
|
228 | "process.env": {
|
229 | NODE_ENV: '"production"'
|
230 | }
|
231 | })
|
232 | ]
|
233 | }).run(function() {});
|
234 | }
|
235 |
|
236 | function watch() {
|
237 | buildReactCore();
|
238 | compiler.watch({
|
239 | poll: true
|
240 | }, function(err, stats) {
|
241 | console.log(stats.toString({
|
242 | colors: true
|
243 | }));
|
244 | });
|
245 | }
|
246 |
|
247 | function build() {
|
248 | buildReactCore();
|
249 | compiler.run(function(err, stats) {
|
250 | console.log(stats.toString({
|
251 | colors: true
|
252 | }));
|
253 | if (stats.hasErrors()) process.exit(2);
|
254 | });
|
255 | }
|
256 |
|
257 | function help() {
|
258 | console.error("Usage:");
|
259 | console.error(" react-beaker watch <source dir>");
|
260 | console.error(" react-beaker build <source dir>");
|
261 | console.error(" react-beaker publish <source dir>");
|
262 | }
|
263 |
|
264 | if (command === "watch") watch();
|
265 | if (command === "build") build();
|
266 | if (command === "publish") build();
|