-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathgulpfile.js
More file actions
245 lines (234 loc) · 6.91 KB
/
Copy pathgulpfile.js
File metadata and controls
245 lines (234 loc) · 6.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
const path = require("path");
const { dest, parallel, series, src, watch } = require("gulp");
// const babel = require("gulp-babel"); // @babel/core, @babel/preset-env, gulp-babel
const bs = require("browser-sync").create();
const clean_css = require("gulp-clean-css");
const closure_compiler = require("google-closure-compiler").gulp();
const favicon = require("favicons").stream;
const fiber = require("fibers");
const filter = require('gulp-filter');
const image_min = require("gulp-imagemin");
const intermediate = require("gulp-intermediate");
const html_min = require("gulp-htmlmin");
const noop = require("through2").obj;
const notify = require("gulp-notify");
const plumber = require("gulp-plumber");
const postcss = require("gulp-postcss");
const pug = require("gulp-pug");
const rollup = require("rollup").rollup;
const sass = require("gulp-sass");
const sourcemaps = require("gulp-sourcemaps");
const ts = require("gulp-typescript").createProject("tsconfig.json");
const trash = require("trash");
sass.compiler = require("sass")
/*
const browser_list = [
"ios >= 8",
"android >= 4.0",
"> 3% in JP"
];
*/
const browser_list = ["defaults"];
const node_modules_dir = __dirname;
const rollup_plugins = [
require("@rollup/plugin-node-resolve").default({
customResolveOptions: {
basedir: node_modules_dir
}
}),
require("@rollup/plugin-commonjs")(),
require("rollup-plugin-sourcemaps")(),
];
const postcss_plugins = [
require("postcss-assets")({ loadPaths: ["src/assets"] }), // TODO: optimizeされたリソースを使うべきかも
require("css-declaration-sorter")({ order: "smacss" }),
require("autoprefixer")({
overrideBrowserslist: browser_list,
cascade: false
}),
];
const error2notify = () =>
plumber({
errorHandler: notify.onError("<%= error.message %>"),
});
const bs_update = bs.stream;
const prod_only = (stream) => (is_prod ? stream : noop()); // 一部処理は、開発時には行わず、製品ビルドでのみ行う
const is_prod = process.argv.includes("--prod");
const dest_dir = ".tmp"; // output folder
const bs_port = 8137;
const bs_ui_port = 8138;
function task_copy() {
return src(["src/**/*", "!src/**/_*", "!src/**/*.+(ts|tsx|pug|sass|html|css)", "!src/favicon.*"], { base: "src" })
.pipe(error2notify())
.pipe(prod_only(image_min()))
.pipe(dest(dest_dir))
.pipe(bs_update());
}
function task_html() {
return src(["src/**/*.html"], { base: "src" })
.pipe(error2notify())
.pipe(prod_only(html_min({
collapseWhitespace: true,
caseSensitive: true,
})))
.pipe(dest(dest_dir))
.pipe(bs_update());
}
function task_css() {
return src("src/**/*.css", { base: "src" })
.pipe(error2notify())
.pipe(postcss(postcss_plugins))
.pipe(clean_css())
.pipe(dest(dest_dir))
.pipe(bs_update());
}
function task_pug() {
return src(["src/**/*.pug", "!**/_*.pug"], { base: "src" })
.pipe(error2notify())
.pipe(pug())
.pipe(prod_only(html_min({
collapseWhitespace: true,
caseSensitive: true,
})))
.pipe(dest(dest_dir))
.pipe(bs_update());
}
function task_sass() {
return src("src/**/*.sass", { base: "src" })
.pipe(error2notify())
.pipe(sass({ outputStyle: "compressed", fiber }))
.pipe(postcss(postcss_plugins))
.pipe(clean_css())
.pipe(dest(dest_dir))
.pipe(bs_update());
}
var rollup_cache;
function task_ts() {
return src("src/**/*.+(ts|tsx)", { base: "src" })
.pipe(error2notify())
.pipe(sourcemaps.init())
.pipe(ts())
/*.pipe(prod_only(cache(
babel({
presets: [["@babel/preset-env", { "targets": { "browsers": browser_list } }]]
}),
{ name: "babel" }
)))*/
.pipe(sourcemaps.write({ includeContent: true }))
.pipe(
intermediate({ output: "bundle" }, (tempDir, done) => {
rollup({
input: `${tempDir}/index.js`,
treeshake: true,
plugins: rollup_plugins,
cache: rollup_cache,
})
.then((bundle) =>
bundle.write({
file: `${tempDir}/bundle/index.js`,
format: "iife",
name: "index_js",
sourcemap: true, // "inline",
sourcemapPathTransform: relPath => {
if (relPath.startsWith("../../")) { // "../index.ts" がエントリーポイント。その上位階層へのパスということは、srcの外部のファイル
return path.relative(node_modules_dir, path.join(`${tempDir}/bundle`, relPath));
} else {
return path.join("src", path.relative("..", relPath));
}
},
})
)
.then(() => done())
.catch((err) => done(err));
}
)
)
.pipe(prod_only(
sourcemaps.init({ loadMaps: true })
))
.pipe(prod_only(
filter(["**", "!**/*.js.map"], { restore: false }) // remove sourcemap
))
.pipe(prod_only(
closure_compiler({
compilation_level: "SIMPLE", // ADVANCED
language_in: "ECMASCRIPT_2019",
language_out: "ECMASCRIPT_2017",
js_output_file: './index.js',
create_source_map: true,
assume_function_wrapper: true,
})
))
.pipe(prod_only(
sourcemaps.write(".", { includeContent: true })
))
.pipe(dest(dest_dir))
.pipe(bs_update());
}
function task_favicon() {
return src("src/favicon.*")
.pipe(error2notify())
.pipe(
favicon({
logging: false,
pipeHTML: false,
replace: true,
pixel_art: false,
icons: {
// Platform Options:
// - offset - offset in percentage
// - background:
// * false - use default
// * true - force use default, e.g. set background for Android icons
// * color - set background for the specified icons
// * mask - apply mask in order to create circle icon (applied by default for firefox). `boolean`
// * overlayGlow - apply glow effect after mask has been applied (applied by default for firefox). `boolean`
// * overlayShadow - apply drop shadow after mask has been applied .`boolean`
android: true,
appleIcon: true,
appleStartup: true,
coast: true,
favicons: true,
firefox: true,
windows: true,
yandex: true,
},
})
)
.pipe(dest(dest_dir))
.pipe(bs_update());
}
function task_clean() {
return trash([dest_dir, ".tmp"]);
}
function task_bs_start(done) {
bs.init({
server: dest_dir,
port: bs_port,
ui: { port: bs_ui_port },
// https: true,
logPrefix: "BrowserSync",
logFileChanges: false,
cors: false,
notify: false,
open: false,
reloadDebounce: 300, // TODO: ちゃんとした値にする
});
done();
}
function task_watch(done) {
watch(["src/**/*", "!src/_*", "!src/**/*.+(ts|tsx|pug|sass|html|css)", "!src/favicon.*"], task_copy);
watch("src/**/*.html", task_html);
watch("src/**/*.css", task_css);
watch("src/**/*.(pug|md)", task_pug); // some pug files includes md
watch(["src/**/*.sass", "src/assets/*"], task_sass);
watch("src/**/*.+(ts|tsx)", task_ts);
watch("src/favicon.*", task_favicon);
done();
}
const task_build = series(
task_clean,
parallel(task_copy, task_html, task_css, task_pug, task_sass, task_ts, task_favicon)
);
exports.build = task_build;
exports.default = exports.watch = series(task_build, task_bs_start, task_watch);