実現したいこと
- dockerを使用
- typescriptのコンパイル
- sassのコンパイル
- ブラウザのautoリロード
- bootstrap使いたい
最初に作成したgulpfile.js
gulpfile.js
const { src, dest, watch, series, parallel } = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const plumber = require("gulp-plumber");
const notify = require("gulp-notify");
const postcss = require("gulp-postcss");
const cssnext = require("postcss-cssnext");
const cleanCSS = require("gulp-clean-css");
const sourcemaps = require("gulp-sourcemaps");
const rename = require("gulp-rename");
//ブラウザリロード
var browserSync = require('browser-sync')
var browserify = require('gulp-browserify');
//typescript
const typescript = require("gulp-typescript").createProject("tsconfig.json");
const uglify = require("gulp-uglify");
//postcss-cssnext ブラウザ対応条件 prefix 自動付与
const browsers = [
'last 2 versions',
'> 5%',
'ie = 11',
'not ie <= 10',
'ios >= 8',
'and_chr >= 5',
'Android >= 5',
];
const preprocessors =[ cssnext(browsers) ];
//参照元パス
const srcPath = {
scss: './src/scss/*.scss',
ts: './src/ts/*.ts',
}
//参照元パス
const destPath = {
css: './www/html/lib/css',
js: './www/html/lib/js',
html: './www/html'
}
const cssSass = () => {
return src(srcPath.scss)
.pipe(sourcemaps.init())
.pipe(sass({ // コンパイル実行(sass->css)
includePaths: './node_modules/bootstrap/scss',
outputStyle: 'expanded'
}))
.pipe(postcss( preprocessors ))//cssnext
.pipe(plumber({
errorHandler: notify.onError('Error:<%= error.message %>')
}
))
.pipe(sourcemaps.write('/maps')) //ソースマップの出力
.pipe(dest(destPath.css))
.pipe(cleanCSS()) // CSS圧縮
}
//typescriptのコンパイル
const jsCompile = () => {
return src(srcPath.ts)
.pipe(
plumber(
{
errorHandler: notify.onError('Error: <%= error.message %>')
}
)
)
.pipe(typescript())
.js
.pipe(uglify({
compress: {
sequences: false
}
}))
.pipe(rename("bundle.js"))
.pipe(dest(destPath.js))
}
const initBrowser = () =>{
let server = browserSync.init({
proxy: 'localhost:<dockerのポート番号>',
startPath : '/index.php'
});
return server;
}
const browserReload = () =>{
browserSync.reload();
}
//ファイル監視
const watchFiles = () => {
watch(srcPath.scss, series(cssSass,browserReload));
watch(srcPath.ts, series(jsCompile,browserReload));
watch("./www/html/*.php",series(browserReload));
}
exports.default = series(series(cssSass, jsCompile,initBrowser), watchFiles);
発生した問題
- bootstrapでエラーが出ている
- browser-syncが動かない
- jsのエラーが発生する
- dockerのサーバーのjs/cssがキャッシュ残ってる?
bootstrapのcssでエラーが発生する問題について
Eror
postcss-custom-properties:~~~variable '--bs-border-radius-pill' is undefined and used without a fallback
これは簡単でした。pipeの順番が間違っていました。
gulpfile.js
const cssSass = () => {
return src(srcPath.scss)
.pipe(sourcemaps.init())
.pipe(postcss( preprocessors )) //sassの前に移動
.pipe(sass({ // コンパイル実行(sass->css)
includePaths: './node_modules/bootstrap/scss',
outputStyle: 'expanded'
}))
browser-syncが動かない
browser-syncの初期化が完了していなかったことが原因なので、完了処理をいれる。
gulpfile.js
const initBrowser = (done) =>{
let server = browserSync.init({
proxy: 'localhost:<dockerのポート番号>',
startPath : '/all.php'
});
done();
return server;
}
jsのエラーが発生
Error
bundle.js:1 Uncaught ReferenceError: exports is not defined
browserifyの導入を行う。
gulpfile.js
const jsCompile = () => {
return src(srcPath.ts)
.pipe(
plumber( //エラーが出ても処理を止めない
{
errorHandler: notify.onError('Error: <%= error.message %>')
}
)
)
.pipe(typescript())
.js
.pipe(browserify({
insertGlobals : true,
debug:true
}))
.pipe(uglify({
compress: {
sequences: false
}
}))
.pipe(rename("bundle.js"))
.pipe(dest(destPath.js))
}
dockerのキャッシュが残っているような気がする・・・
一応jsやcssにハッシュをつけておく
画像などにも付ける場合は、pipeで増やす。
gulpfile.js
const addHash = () =>{
return src([
destPath.html+'/index.php'
])
.pipe(replace('.css"','.css?' + hash + '"'))
.pipe(replace('.js"','.js?' + hash + '"'))
}
上記の1~4までの問題を解決したgulpfile.js
gulpfile.js
const { src, dest, watch, series, parallel } = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const plumber = require("gulp-plumber");
const notify = require("gulp-notify");
const postcss = require("gulp-postcss");
const cssnext = require("postcss-cssnext");
const cleanCSS = require("gulp-clean-css");
const sourcemaps = require("gulp-sourcemaps");
const rename = require("gulp-rename");
const replace = require("gulp-replace");
const crypto = require('crypto');
const hash = crypto.randomBytes(8).toString('hex');
//ブラウザリロード
var browserSync = require('browser-sync')
var browserify = require('gulp-browserify');
//typescript
const typescript = require("gulp-typescript").createProject("tsconfig.json");
const uglify = require("gulp-uglify");
//postcss-cssnext ブラウザ対応条件 prefix 自動付与
const browsers = [
'last 2 versions',
'> 5%',
'ie = 11',
'not ie <= 10',
'ios >= 8',
'and_chr >= 5',
'Android >= 5',
];
const preprocessors =[ cssnext(browsers) ];
//参照元パス
const srcPath = {
scss: './src/scss/*.scss',
ts: './src/ts/*.ts',
}
//参照元パス
const destPath = {
css: './www/html/lib/css',
js: './www/html/lib/js',
html: './www/html'
}
const cssSass = () => {
return src(srcPath.scss)
.pipe(sourcemaps.init())
.pipe(postcss( preprocessors ))//cssnext
.pipe(sass({ // コンパイル実行(sass->css)
includePaths: './node_modules/bootstrap/scss',
outputStyle: 'expanded'
}))
.pipe(plumber({
errorHandler: notify.onError('Error:<%= error.message %>')
}
))
.pipe(sourcemaps.write('/maps')) //ソースマップの出力
.pipe(dest(destPath.css))
.pipe(cleanCSS()) // CSS圧縮
}
//typescriptのコンパイル
const jsCompile = () => {
return src(srcPath.ts)
.pipe(
plumber(
{
errorHandler: notify.onError('Error: <%= error.message %>')
}
)
)
.pipe(typescript())
.js
.pipe(browserify({
insertGlobals : true,
debug:true
}))
.pipe(uglify({
compress: {
sequences: false
}
}))
.pipe(rename("bundle.js"))
.pipe(dest(destPath.js))
}
const initBrowser = (done) =>{
let server = browserSync.init({
proxy: 'localhost:<dockerのポート番号>',
startPath : '/index.php'
});
done();
return server;
}
const addHash = () =>{
return src([
destPath.html+'/index.php'
])
.pipe(replace('.css"','.css?' + hash + '"'))
.pipe(replace('.js"','.js?' + hash + '"'))
}
const browserReload = () =>{
browserSync.reload();
}
//ファイル監視
const watchFiles = () => {
watch(srcPath.scss, series(cssSass,addHash,browserReload));
watch(srcPath.ts, series(jsCompile,addHash,browserReload));
watch("./www/html/*.php",series(addHash,browserReload));
}
exports.default = series(series(cssSass, jsCompile,addHash,initBrowser), watchFiles);
最後にもう一つ
browser-syncが1度しか動かない。
もう一箇所reload完了処理をいれるのを忘れてました。
gulpfile.js
const browserReload = (done) =>{
browserSync.reload();
done();
}
完成したgulpfile
gulpfile.js
const { src, dest, watch, series, parallel } = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const plumber = require("gulp-plumber");
const notify = require("gulp-notify");
const postcss = require("gulp-postcss");
const cssnext = require("postcss-cssnext");
const cleanCSS = require("gulp-clean-css");
const sourcemaps = require("gulp-sourcemaps");
const rename = require("gulp-rename");
const replace = require("gulp-replace");
const crypto = require('crypto');
const hash = crypto.randomBytes(8).toString('hex');
//ブラウザリロード
var browserSync = require('browser-sync')
var browserify = require('gulp-browserify');
//typescript
const typescript = require("gulp-typescript").createProject("tsconfig.json");
const uglify = require("gulp-uglify");
//postcss-cssnext ブラウザ対応条件 prefix 自動付与
const browsers = [
'last 2 versions',
'> 5%',
'ie = 11',
'not ie <= 10',
'ios >= 8',
'and_chr >= 5',
'Android >= 5',
];
const preprocessors =[ cssnext(browsers) ];
//参照元パス
const srcPath = {
scss: './src/scss/*.scss',
ts: './src/ts/*.ts',
}
//参照元パス
const destPath = {
css: './www/html/lib/css',
js: './www/html/lib/js',
html: './www/html'
}
const cssSass = () => {
return src(srcPath.scss)
.pipe(sourcemaps.init())
.pipe(postcss( preprocessors ))//cssnext
.pipe(sass({ // コンパイル実行(sass->css)
includePaths: './node_modules/bootstrap/scss',
outputStyle: 'expanded'
}))
.pipe(plumber({
errorHandler: notify.onError('Error:<%= error.message %>')
}
))
.pipe(sourcemaps.write('/maps')) //ソースマップの出力
.pipe(dest(destPath.css))
.pipe(cleanCSS()) // CSS圧縮
}
//typescriptのコンパイル
const jsCompile = () => {
return src(srcPath.ts)
.pipe(
plumber(
{
errorHandler: notify.onError('Error: <%= error.message %>')
}
)
)
.pipe(typescript())
.js
.pipe(browserify({
insertGlobals : true,
debug:true
}))
.pipe(uglify({
compress: {
sequences: false
}
}))
.pipe(rename("bundle.js"))
.pipe(dest(destPath.js))
}
const initBrowser = (done) =>{
let server = browserSync.init({
proxy: 'localhost:<dockerのポート番号>',
startPath : '/index.php'
});
done();
return server;
}
const addHash = () =>{
return src([
destPath.html+'/index.php'
])
.pipe(replace('.css"','.css?' + hash + '"'))
.pipe(replace('.js"','.js?' + hash + '"'))
}
const browserReload = () =>{
browserSync.reload();
done();
}
//ファイル監視
const watchFiles = () => {
watch(srcPath.scss, series(cssSass,addHash,browserReload));
watch(srcPath.ts, series(jsCompile,addHash,browserReload));
watch("./www/html/*.php",series(addHash,browserReload));
}
exports.default = series(series(cssSass, jsCompile,addHash,initBrowser), watchFiles);
dockerの設定ファイル
docker-compose.yml
version: "1"
services:
app:
build:
context: "docker/app/"
ports:
- <dockerのポート番号>:80
working_dir: /var/www
volumes:
- "./www/:/var/www"
- "./docker/app/apache2/apache2.conf:/etc/apache2/apache2.conf"
- "./docker/app/apache2/sites-available/000-default.conf:/etc/apache2/sites-available/000-default.conf"
volumes:
storage: