tag:crieit.net,2005:https://crieit.net/tags/Sass/feed 「Sass」の記事 - Crieit Crieitでタグ「Sass」に投稿された最近の記事 2021-07-05T20:32:23+09:00 https://crieit.net/tags/Sass/feed tag:crieit.net,2005:PublicArticle/17485 2021-07-05T20:32:23+09:00 2021-07-05T20:32:23+09:00 https://crieit.net/posts/node-sass-adjust-node16-20210705 gulp-sass を Node.js v16 環境に合わせて調整する <p>Node.js の 16系 を試そうとしたら gulp-sass, node-sass 周りでエラーが発生したので対処をまとめておきます。</p> <h2 id="経緯"><a href="#%E7%B5%8C%E7%B7%AF">経緯</a></h2> <p>まず前提として</p> <ul> <li>Dart Sass で <code>/</code> を使った徐算が非推奨となった (代わりに <code>math.div</code> を使えとのこと) <ul> <li>参考: <a target="_blank" rel="nofollow noopener" href="https://labor.ewigleere.net/2021/06/07/dart-sass-warning-slash-as-division/">Dart Sass で DEPRECATION WARNING: Using / for division is deprecated and will be removed in Dart Sass 2.0.0. の警告が表示される - Ewig Leere(Lab2)</a></li> </ul></li> <li>上述現象を回避するため、 <code>sass</code> のバージョンを <code>1.32.12</code> で固定していた</li> </ul> <p>という事情があります。</p> <h2 id="現象"><a href="#%E7%8F%BE%E8%B1%A1">現象</a></h2> <p>この状態で Node.js のバージョンを 16系 に切り替えて <code>yarn</code> 。</p> <pre><code class="bash">error /home/node/app/node_modules/node-sass: Command failed. Exit code: 1 Command: node scripts/build.js Arguments: Directory: /home/node/app/node_modules/node-sass Output: Building: /usr/local/bin/node /home/node/app/node_modules/node-gyp/bin/node-gyp.js rebuild --verbose --libsass_ext= --libsass_cflags= --libsass_ldflags= --libsass_library= # 略 In file included from /home/node/.node-gyp/16.3.0/include/node/v8.h:30, from /home/node/.node-gyp/16.3.0/include/node/node.h:63, from ../../nan/nan.h:56, from ../src/binding.cpp:1: /home/node/.node-gyp/16.3.0/include/node/v8-internal.h: In function 'void v8::internal::PerformCastCheck(T*)': /home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:38: error: 'remove_cv_t' is not a member of 'std' !std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data); ^~~~~~~~~<del> /home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:38: note: suggested alternative: 'remove_cv' !std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data); ^</del>~~~~~~<del> remove_cv /home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:38: error: 'remove_cv_t' is not a member of 'std' /home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:38: note: suggested alternative: 'remove_cv' !std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data); ^</del>~~~~~~<del> remove_cv /home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:50: error: template argument 2 is invalid !std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data); ^ /home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:63: error: '::Perform' has not been declared !std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data); ^</del>~~<del> /home/node/.node-gyp/16.3.0/include/node/v8-internal.h:452:63: note: suggested alternative: 'herror' !std::is_same<Data, std::remove_cv_t<T>>::value>::Perform(data); ^</del>~~<del> herror ../src/binding.cpp: In function 'Nan::NAN_METHOD_RETURN_TYPE render(Nan::NAN_METHOD_ARGS_TYPE)': ../src/binding.cpp:284:98: warning: cast between incompatible function types from 'void (*)(uv_work_t*)' {aka 'void (*)(uv_work_s*)'} to 'uv_after_work_cb' {aka 'void (*)(uv_work_s*, int)'} [-Wcast-function-type] int status = uv_queue_work(uv_default_loop(), &ctx_w->request, compile_it, (uv_after_work_cb)MakeCallback); ^</del>~~~~~~~<del> ../src/binding.cpp: In function 'Nan::NAN_METHOD_RETURN_TYPE render_file(Nan::NAN_METHOD_ARGS_TYPE)': ../src/binding.cpp:320:98: warning: cast between incompatible function types from 'void (*)(uv_work_t*)' {aka 'void (*)(uv_work_s*)'} to 'uv_after_work_cb' {aka 'void (*)(uv_work_s*, int)'} [-Wcast-function-type] int status = uv_queue_work(uv_default_loop(), &ctx_w->request, compile_it, (uv_after_work_cb)MakeCallback); ^</del>~~~~~~~<del> In file included from ../../nan/nan.h:56, from ../src/binding.cpp:1: ../src/binding.cpp: At global scope: /home/node/.node-gyp/16.3.0/include/node/node.h:806:43: warning: cast between incompatible function types from 'void (*)(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE)' {aka 'void (*)(v8::Local<v8::Object>)'} to 'node::addon_register_func' {aka 'void (*)(v8::Local<v8::Object>, v8::Local<v8::Value>, void*)'} [-Wcast-function-type] (node::addon_register_func) (regfunc), \ ^ /home/node/.node-gyp/16.3.0/include/node/node.h:840:3: note: in expansion of macro 'NODE_MODULE_X' NODE_MODULE_X(modname, regfunc, NULL, 0) // NOLINT (readability/null_usage) ^</del>~~~~~~~~<del> ../src/binding.cpp:358:1: note: in expansion of macro 'NODE_MODULE' NODE_MODULE(binding, RegisterModule); ^</del>~~~~~~~~ make: *** [binding.target.mk:133: Release/obj.target/binding/src/binding.o] Error 1 make: Leaving directory '/home/node/app/node_modules/node-sass/build' gyp ERR! build error gyp ERR! stack Error: `make` failed with exit code: 2 gyp ERR! stack at ChildProcess.onExit (/home/node/app/node_modules/node-gyp/lib/build.js:262:23) gyp ERR! stack at ChildProcess.emit (node:events:394:28) gyp ERR! stack at Process.ChildProcess._handle.onexit (node:internal/child_process:290:12) gyp ERR! System Linux 5.10.25-linuxkit gyp ERR! command "/usr/local/bin/node" "/home/node/app/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--verbose" "--libsass_ext=" "--libsass_cflags=" "--libsass_ldflags=" "--libsass_library=" gyp ERR! cwd /home/node/app/node_modules/node-sass gyp ERR! node -v v16.3.0 </code></pre> <p>……滅茶苦茶怒られました (Docker内のLinux環境)。</p> <p>ちなみに Windows環境だと <code>yarn</code> 時にはエラーにはなりませんが、 Gulpタスク を走らせた際に同様のエラーメッセージが表示されます。</p> <p><a href="https://crieit.now.sh/upload_images/68677d73f1123631b69e1a1fa1061c7b60e2edbdef2fa.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/68677d73f1123631b69e1a1fa1061c7b60e2edbdef2fa.jpg?mw=700" alt="Windows環境でのエラーメッセージ" /></a></p> <h2 id="対処1 (sass, gulp-sass のバージョンを上げる)"><a href="#%E5%AF%BE%E5%87%A61+%28sass%2C+gulp-sass+%E3%81%AE%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%82%92%E4%B8%8A%E3%81%92%E3%82%8B%29">対処1 (sass, gulp-sass のバージョンを上げる)</a></h2> <p>そこでまずは <code>sass</code> のバージョンを上げます。</p> <p>ちなみに、 <code>1.35.0</code>以降 では <code>quietDeps: true</code> のフラグを追加することで、冒頭の警告を非表示にできるようになったとのことなので、そもそもの問題は回避できるはずです。</p> <pre><code class="json"> "devDependencies": { // 略 "gulp-sass": "^4.1.0", "sass": "1.35.1", // 1.32.12 からアップデート "fibers": "^5.0.0", "gulp-autoprefixer": "^7.0.1", // 略 } </code></pre> <p>これで <code>yarn</code> してみましたが、ダメ。</p> <p>ふと <code>gulp-sass</code> を見てみると、いつの間にか <code>5.0.0</code> がリリースされているではありませんか。</p> <pre><code class="json"> "devDependencies": { // 略 "gulp-sass": "^5.0.0", // 4.1.0 からアップデート "sass": "1.35.1", // 1.32.12 からアップデート "fibers": "^5.0.0", "gulp-autoprefixer": "^7.0.1", // 略 } </code></pre> <p>そこで、 <code>gulp-sass</code> も上げます。これで <code>yarn</code> すると正常に完了。</p> <p>安心して Gulpタスク を走らせると……</p> <pre><code class="bash">../src/coroutine.cc:134: void* find_thread_id_key(void*): Assertion `thread_id_key != 0x7777' failed. </code></pre> <p>…別のエラーで怒られました。</p> <h2 id="対処2 (fibers を削除)"><a href="#%E5%AF%BE%E5%87%A62+%28fibers+%E3%82%92%E5%89%8A%E9%99%A4%29">対処2 (fibers を削除)</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/67330252/thread-id-key-0x7777-function-find-thread-id-key-file-src-coroutine-cc">node.js - (thread_id_key != 0x7777), function find_thread_id_key, file ../src/coroutine.cc, line 134 - Stack Overflow</a></li> </ul> <p>検索すると上述のエラーは <code>fibers</code> が Node.js 16系 に対応していないために発生している模様。</p> <p>そのため、 <code>fibers</code> を削除します。</p> <pre><code class="json"> "devDependencies": { // 略 "gulp-sass": "^5.0.0", // 4.1.0 からアップデート "sass": "1.35.1", // 1.32.12 からアップデート "gulp-autoprefixer": "^7.0.1", // 略 } </code></pre> <p>併せてタスクも書き換えます。</p> <pre><code class="javascript">const sass = require('gulp-sass'); sass.compiler = require('sass'); //const Fiber = require('fibers'); // 略 .pipe(sass({ // fiber: Fiber, outputStyle: 'compressed', quietDeps: true // 警告回避のために追加 }).on('error', sass.logError)) // 略 </code></pre> <p><code>fibers</code> 関係を削除。</p> <p>これで <code>yarn</code> し直してタスクを再実行。</p> <pre><code class="bash">Error in plugin "gulp-sass" Message: gulp-sass 5 does not have a default Sass compiler; please set one yourself. Both the `sass` and `node-sass` packages are permitted. For example, in your gulpfile: var sass = require('gulp-sass')(require('sass')); </code></pre> <p>……別のエラーが発生しました。どうやら <code>gulp-sass</code> の Scssトランスパイラ の指定方法が変わったようです。</p> <h2 id="対処3 (gulp-sass のScssトランスパイラ指定方法を変更)"><a href="#%E5%AF%BE%E5%87%A63+%28gulp-sass+%E3%81%AEScss%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B9%E3%83%91%E3%82%A4%E3%83%A9%E6%8C%87%E5%AE%9A%E6%96%B9%E6%B3%95%E3%82%92%E5%A4%89%E6%9B%B4%29">対処3 (gulp-sass のScssトランスパイラ指定方法を変更)</a></h2> <pre><code class="javascript">const sass = require('gulp-sass')(require('sass')); //const Fiber = require('fibers'); // 略 .pipe(sass({ // fiber: Fiber, outputStyle: 'compressed', quietDeps: true // 警告回避のために追加 }).on('error', sass.logError)) // 略 </code></pre> <p>これでようやくタスクが正常に走るようになりました。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li>Dart Sass の警告回避: <ul> <li><a target="_blank" rel="nofollow noopener" href="https://sass-lang.com/documentation/js-api#quietdeps">Sass: JavaScript API</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/twbs/bootstrap/issues/34051">Sass deprecation warning: Using `/` for division is deprecated · Issue #34051 · twbs/bootstrap · GitHub</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/sass/dart-sass/issues/1333">support quietDeps flag · Issue #1333 · sass/dart-sass · GitHub</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/sass/dart-sass/issues/672">Add a --quiet-upstream flag · Issue #672 · sass/dart-sass · GitHub</a></li> </ul></li> <li>fibers: <a target="_blank" rel="nofollow noopener" href="https://stackoverflow.com/questions/67330252/thread-id-key-0x7777-function-find-thread-id-key-file-src-coroutine-cc">node.js - (thread_id_key != 0x7777), function find_thread_id_key, file ../src/coroutine.cc, line 134 - Stack Overflow</a></li> <li>gulp-sass: <a target="_blank" rel="nofollow noopener" href="https://www.npmjs.com/package/gulp-sass">gulp-sass - npm</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/17368 2021-06-07T23:12:54+09:00 2021-06-07T23:12:54+09:00 https://crieit.net/posts/dart-sass-warning-slash-as-division-20210607 Dart Sass で DEPRECATION WARNING: Using / for division is deprecated and will be removed in Dart Sass 2.0.0. の警告が表示される <h2 id="現象"><a href="#%E7%8F%BE%E8%B1%A1">現象</a></h2> <p>最近 Dart Sass で Scss をトランスパイルすると、</p> <blockquote> <p>DEPRECATION WARNING: Using / for division is deprecated and will be removed in Dart Sass 2.0.0.</p> </blockquote> <p>という警告が表示されるようになりました。</p> <p>より詳細には以下のような感じです。</p> <pre><code class="bash">DEPRECATION WARNING: Using / for division is deprecated and will be removed in Dart Sass 2.0.0. Recommendation: math.div($spacer, 2) More info and automated migrator: https://sass-lang.com/d/slash-div ╷ 308 │ $headings-margin-bottom: $spacer / 2 !default; │ ^^^^^^^^^^^ ╵ node_modules\bootstrap-honoka\scss\honoka\_variables.scss 308:31 @import src\scss\global\honoka\_honokaImport.scss 7:9 @forward src\scss\global\_framework.scss 3:1 @use src\scss\foundation\_override.scss 4:1 @use src\scss\foundation\_index.scss 3:1 @use src\scss\contents.scss 8:1 root stylesheet </code></pre> <h2 id="調査"><a href="#%E8%AA%BF%E6%9F%BB">調査</a></h2> <p>調べると、 Dart Sass では徐算に <code>/</code> を使った記述 (上述の例では <code>$spacer / 2</code> ) は非推奨となり、代わりに <code>math.div($spacer, 2)</code> というように、ビルトインモジュールの <code>math</code> を使うように求められるようです。</p> <p>なお、将来的には非推奨ではなく使用不可にしていく模様。</p> <p>さて、問題はこの警告、大半が Bootstrap の中で発生しているということ。</p> <p>自分で書いたコードのみならば修正していくのも吝かではないですが、 Bootstrap 本体となるとあまり手は入れたくないし、量も大量にあると想定されるので面倒なことになりそうです。</p> <h2 id="回避"><a href="#%E5%9B%9E%E9%81%BF">回避</a></h2> <p>上述より、根本的対処ではなく Dart Sass のパッケージ指定を固定するという一時的な回避策で逃げたいと思います。</p> <pre><code class="json"> // 略 "devDependencies": { // 略 "sass": "1.32.12", // 略 }, "resolutions": { // 略 "sass": "1.32.12" }, // 略 </code></pre> <p>これでひとまず警告は出なくなりました。</p> <p>後は Bootstrap 等が対応してくれることを祈る感じですかね……。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://sass-lang.com/documentation/breaking-changes/slash-div">Sass: Breaking Change: Slash as Division</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://www.webdesignleaves.com/wp/htmlcss/1956/">Bootstrap 5 のビルドで DEPRECATION WARNING: Using / for division is deprecated | Web Design Leaves</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://koredana.info/blog/sass-math-div">Sassで除算するときはsass:mathモジュールのdiv関数を使おう | コレ棚</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/16786 2021-03-28T18:20:44+09:00 2021-08-08T16:13:11+09:00 https://crieit.net/posts/VSCode-Web 【VSCode】拡張機能一覧(主にWeb系システム開発用) <p>個人用メモ。<br /> 主にPHPを使用して開発する環境で使用している拡張機能一覧。<br /> (他のも混じっているけど)<br /> (後で追加・変更・削除するかも)</p> <h1 id="VSCode"><a href="#VSCode">VSCode</a></h1> <ul> <li><p>Bookmarks<br />  あらかじめソースコード中にブックマークを設定しておくと、他の場所からブックマークまで一瞬で移動することが出来る。</p></li> <li><p>indent-rainbow<br />  インデントを色付きで表示してくれる。</p></li> <li><p>Japanese Language Pack for Visual Studio Code<br />  VSCodeの日本語化。</p></li> </ul> <h1 id="HTML"><a href="#HTML">HTML</a></h1> <ul> <li><p>Auto Close Tag<br />  自動的に閉じタグを追記してくれる。</p></li> <li><p>Auto Rename Tag<br />  タグを変更すると、対応する閉じタグを自動的に変更してくれる。</p></li> <li><p>HTML Snippets<br />  HTMLの予測変換を表示してくれる。</p></li> <li><p>HTMLHint<br />  HTMLの文法チェックをしてくれる。</p></li> </ul> <h1 id="PHP(Laravel)"><a href="#PHP%28Laravel%29">PHP(Laravel)</a></h1> <ul> <li><p>Bracket Pair Colorizer 2<br />  メソッドやArrayなどで、対となるカッコを色付きで表示してくれる。</p></li> <li><p>php cs fixer<br />  PHPソースを自動整形してくれる。<br />  ※別途、「php-cf-fixer.phar」のインストールが必要。</p></li> <li><p>PHP Debug<br />  PHPをステップ実行してデバッグできるようになる。</p></li> <li><p>PHP IntelliSense<br />  PHPの予測変換を表示してくれる。</p></li> </ul> <p>【2021.8.8 追加】<br /> * Laravel Blade Snippets<br />  Laravelのbladeファイル内のタグやディレクティブを色付きで表示してくれる。</p> <ul> <li>Laravel Blade formatter<br />  Laravelのbladeファイル用のフォーマッタ。<br />  blade独自のディレクティブもインデントしてくれる(これ重要)。</li> </ul> <h1 id="JavaScript(Node.js,Vue.js)"><a href="#JavaScript%28Node.js%2CVue.js%29">JavaScript(Node.js,Vue.js)</a></h1> <ul> <li><p>ESLint<br />  JavaScriptの構文チェックをリアルタイムで実行してくれる。<br />  ※Vue.jsで使用するには設定が必要。</p></li> <li><p>JavaScript (ES6) code snippets<br />  JavaScriptの予測変換を表示してくれる。</p></li> <li><p>Vetur<br />  Vue.jsコードのシンタックスハイライトやコード補完、リント、フォーマットを行ってくれる。</p></li> </ul> <h1 id="CSS(Sass,SCSS)"><a href="#CSS%28Sass%2CSCSS%29">CSS(Sass,SCSS)</a></h1> <ul> <li><p>IntelliSense for CSS class names in HTML<br />  CSSクラス名を入力するときに、入力補完してくれる。</p></li> <li><p>SCSS Formatter<br />  SCSSコードを自動整形してくれる。</p></li> </ul> <h1 id="その他"><a href="#%E3%81%9D%E3%81%AE%E4%BB%96">その他</a></h1> <ul> <li><p>Log File Highlighter<br />  ログファイルの内容を色付きで表示してくれる。</p></li> <li><p>MySQL<br />  VSCodeでMySQLを使用可能にする。</p></li> <li><p>Rainbow CSV<br />  CSVファイルをカラムごとに色分けして表示してくれる。</p></li> <li><p>Regex Previewer<br />  正規表現の実行結果をプレビュー表示してくれる。</p></li> <li><p>SFTP<br />  サーバへ自動的にソースファイルをアップロードしてくれる。</p></li> </ul> <h1 id="【参考】"><a href="#%E3%80%90%E5%8F%82%E8%80%83%E3%80%91">【参考】</a></h1> <p>「Visual Studio Code」をインストールしてPHPコードのデバッグ環境を設定する方法<br /> <a target="_blank" rel="nofollow noopener" href="https://incloop.com/visualstudiocodeのデバッグ設定/">https://incloop.com/visualstudiocodeのデバッグ設定/</a></p> <p>Visual Studio Codeで作るPHP開発環境のおすすめ拡張機能17選<br /> <a target="_blank" rel="nofollow noopener" href="https://wonwon-eater.com/vscode-php-plugin/">https://wonwon-eater.com/vscode-php-plugin/</a></p> <p>VScodeの日本語化ができない 変わらない時の対処法[Visual Studio Code]<br /> <a target="_blank" rel="nofollow noopener" href="https://rabotiku-sato.com/vscode-japanese-setting">https://rabotiku-sato.com/vscode-japanese-setting</a></p> <p>vscodeでVue.jsを書くときに使っているプラグインとか<br /> <a target="_blank" rel="nofollow noopener" href="https://qiita.com/dayoshix/items/c61a75a971331418c348">https://qiita.com/dayoshix/items/c61a75a971331418c348</a></p> <p>【HTML編】Visual Studio Code おすすめプラグイン紹介 #02<br /> <a target="_blank" rel="nofollow noopener" href="https://so-da.tech/tech/vscode/vscd3/">https://so-da.tech/tech/vscode/vscd3/</a></p> <p>VSCodeのAuto Rename Tagで閉じタグも自動変更<br /> <a target="_blank" rel="nofollow noopener" href="https://tech.pjin.jp/blog/2020/04/27/vscode_extension_auto_rename_tag/">https://tech.pjin.jp/blog/2020/04/27/vscode_extension_auto_rename_tag/</a></p> <p>VSCode で HTML の文法チェックを行う拡張機能 HTMLHint<br /> <a target="_blank" rel="nofollow noopener" href="https://loumo.jp/archives/26229">https://loumo.jp/archives/26229</a></p> <p>VSCode拡張機能『indent-rainbow』でインデントを虹色にする方法<br /> <a target="_blank" rel="nofollow noopener" href="https://onedarling.site/programming/tool/vscode-indent-rainbow/">https://onedarling.site/programming/tool/vscode-indent-rainbow/</a></p> <p>【2020年版】VSCodeでhtml/css/jsの拡張機能おすすめ<br /> <a target="_blank" rel="nofollow noopener" href="https://uetani33.net/vscode-web-extensions/#toc_id_3_2">https://uetani33.net/vscode-web-extensions/#toc_id_3_2</a></p> <p>VSCode使い必見!?使って便利な Visual Studio Code 拡張機能10選<br /> <a target="_blank" rel="nofollow noopener" href="https://www.geekfeed.co.jp/geekblog/vscode_extension">https://www.geekfeed.co.jp/geekblog/vscode_extension</a></p> <p>【超便利】VSCodeでMySQLを利用する方法<br /> <a target="_blank" rel="nofollow noopener" href="https://newmtube07.com/vscode-mysql/">https://newmtube07.com/vscode-mysql/</a></p> <p>[Visual Studio Code] PHPのコードを整形する「php cs fixer」の設定<br /> <a target="_blank" rel="nofollow noopener" href="https://www.searchlight8.com/visual-studio-code-php/">https://www.searchlight8.com/visual-studio-code-php/</a></p> <p>VSCode(Visual Studio Code)でSFTP・FTP経由でファイルを自動アップロードや同期できる拡張機能「SFTP」が超便利<br /> <a target="_blank" rel="nofollow noopener" href="https://www.karelie.net/vscode-sftp/">https://www.karelie.net/vscode-sftp/</a></p> <p>Windows10でVisual Studio Code + vue-cliの開発環境構築メモ<br /> <a target="_blank" rel="nofollow noopener" href="https://belhb.hateblo.jp/entry/2020/08/08/142540">https://belhb.hateblo.jp/entry/2020/08/08/142540</a></p> <p>【2021.8.8 追加】<br /> LaravelでVisual Studio Codeを使う時に入れておきたい拡張機能3選<br /> <a target="_blank" rel="nofollow noopener" href="https://biz.addisteria.com/laravel-vscode/">https://biz.addisteria.com/laravel-vscode/</a></p> <p>Laravel blade formatter VSCode Extensionを作った<br /> <a target="_blank" rel="nofollow noopener" href="https://shufo.dev/2020/10/03/published-vscode-blade-formatter/">https://shufo.dev/2020/10/03/published-vscode-blade-formatter/</a></p> <p>VSCodeでBladeテンプレートを整形する<br /> <a target="_blank" rel="nofollow noopener" href="https://blog.nplpl.com/310">https://blog.nplpl.com/310</a></p> acmz tag:crieit.net,2005:PublicArticle/16250 2020-12-02T23:50:23+09:00 2020-12-21T23:35:58+09:00 https://crieit.net/posts/bootstrap-paint-in-variable-20201202 Dart Sass (@use, @forward 使用)で Bootstrap 4 の変数やマップを上書きする <p>Dart Sass (<code>@use</code>, <code>@forward</code> 使用)で Bootstrap 4 の変数・マップを上書きしたくなったので実験してみました。</p> <h2 id="今まで (node-sass / LibSass)"><a href="#%E4%BB%8A%E3%81%BE%E3%81%A7+%28node-sass+%2F+LibSass%29">今まで (node-sass / LibSass)</a></h2> <h3 id="前提"><a href="#%E5%89%8D%E6%8F%90">前提</a></h3> <pre><code class="bash"> / └ src/ ├ html/ │ └ index.html │ └ scss/ ├ assets/ │ └ bootstrap/ │ │ └ bootstrap/ │ │ └ 略 │ └ bootstrap.scss │ ├ foundation/ │ ├ _index.scss │ ├ _mixin.scss │ └ _variables.scss │ ├ layout/ │ ├ _l-footer.scss │ ├ _l-header.scss │ └ _l-main.scss │ ├ object/ │ ├ component/ │ │ └ 略 │ ├ project/ │ │ └ 略 │ └ utility/ │ └ 略 │ └ index.scss </code></pre> <p>今回の検証で使用するプロジェクトのディレクトリ構造は、このような状態とします。</p> <h3 id="src/html/index.html"><a href="#src%2Fhtml%2Findex.html">src/html/index.html</a></h3> <pre><code class="html"><div class="mt-4"> <a href="#" class="btn btn-primary m-3">プライマリーボタン</a><!-- プライマリーカラーのボタン --> <a href="#" class="btn btn-main m-3">メインボタン</a><!-- デフォルトにはないボタン --> </div> </code></pre> <p>例として、こんな HTML があったとして。</p> <h3 id="src/scss/foundation/_scss_variable.scss"><a href="#src%2Fscss%2Ffoundation%2F_scss_variable.scss">src/scss/foundation/_scss_variable.scss</a></h3> <pre><code class="scss">$theme-colors: ( /* 上書き */ primary: $own-color, /* デフォルトにないカラーの追加 */ main: $own-main-color, ); </code></pre> <p>マップの定義を上書きするコードを書きます。</p> <h3 id="src/scss/foundation/_index.scss"><a href="#src%2Fscss%2Ffoundation%2F_index.scss">src/scss/foundation/_index.scss</a></h3> <pre><code class="scss">@import "variables"; //変数(Bootstrap の変数上書きのコードあり) @import "mixin"; @import "../assets/bootstrap/bootstrap"; //bootstrap </code></pre> <p>同じ <code>foundation</code> の中に読み込み用の Scss を用意します。</p> <p>注意する点としては、「 Bootstrap の Scss を読み込むより前に、 Bootstrap の変数(マップ)を上書きするための自前の定義が書かれた Scss を読み込む」ということ。</p> <h3 id="src/scss/index.scss"><a href="#src%2Fscss%2Findex.scss">src/scss/index.scss</a></h3> <pre><code class="scss">@import "./foundation/index"; //読み込み </code></pre> <p>最後に、実際に <code>index.css</code> にコンパイルされる <code>src/scss/index.scss</code> で <code>src/scss/foundation/_index.scss</code> を読み込みます。</p> <p>今までは、これで変数の上書きができました。</p> <h2>Dart Sass での検証1 (失敗 / 単純に <code>@import</code> を <code>@use</code>, <code>@forward</code> に書き換え)</h2> <p>さて、ここで単純に今まで <code>@import</code> で記述していたのを <code>@use</code>, <code>@forward</code> に書き換えてみます。</p> <h3 id="src/scss/foundation/_scss_variable.scss"><a href="#src%2Fscss%2Ffoundation%2F_scss_variable.scss">src/scss/foundation/_scss_variable.scss</a></h3> <pre><code class="scss">$theme-colors: ( /* 上書き */ primary: $own-color, /* デフォルトにないカラーの追加 */ main: $own-main-color, ); </code></pre> <p>上書きしたい変数(マップ)の定義はそのまま。</p> <h3 id="src/scss/foundation/_index.scss"><a href="#src%2Fscss%2Ffoundation%2F_index.scss">src/scss/foundation/_index.scss</a></h3> <pre><code class="scss">@forward "scss_variables"; //変数(Bootstrap の変数上書きのコードあり) @forward "mixin"; @forward "../assets/bootstrap/bootstrap"; //bootstrap </code></pre> <p>今度は <code>@import</code> ではなく、 <code>@forward</code> に書き換えます。</p> <h3 id="src/scss/layout/_l-header.scss"><a href="#src%2Fscss%2Flayout%2F_l-header.scss">src/scss/layout/_l-header.scss</a></h3> <pre><code class="scss">@use "../foundation" as f; .l-header { .navbar-brand { &, &:link, &:visited { color: f.$own-main-color; } &:hover, &:active, &:focus { color: f.$own-main-color_l; } } } // 略 </code></pre> <p>実際に <code>src/scss/foundation/_index.scss</code> を読み込んで使用する Scss で <code>@use</code> による読み込みを行います。</p> <h3 id="src/scss/index.scss"><a href="#src%2Fscss%2Findex.scss">src/scss/index.scss</a></h3> <pre><code class="scss">@use "layout/l-header"; //_l-header.scss の中で @use を使って src/scss/foundation/_index.scss を読み込み、使用 @use "layout/l-main"; @use "layout/l-footer"; </code></pre> <p>こんな形に書き換えます。</p> <p>流れとしては、「<code>src/scss/index.scss</code> -(<code>@use</code>)-> <code>src/scss/layout/_l-header.scss</code> -(<code>@forward</code>)-> <code>src/scss/foundation/_index.scss</code>」という関係。</p> <p>この状態で Dart Sass によるコンパイルを実行すると、<code>$theme-colors</code> の変数名が重複しているのでエラーになってしまいます。</p> <pre><code class="bash">Error: src/scss/foundation/_index.scss Error: Two forwarded modules both define a variable named $theme-colors. ╷ 3 │ @forward "variables"; │ ━━━━━━━━━━━━━━━━━━━━ original @forward ... │ 5 │ @forward "../assets/bootstrap/bootstrap"; //bootstrap │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ new @forward ╵ src/scss/foundation/_index.scss 5:1 @use src/scss/layout/_l-header.scss 3:1 @use src/scss/index.scss 8:1 root stylesheet </code></pre> <p>回避するためにはいくつかの方法が考えられますが、 Bootstrap 4 の <code>@import</code> を書き換えていくのは大変な上に既存ライブラリに手を入れるのはできれば避けたいので今回は不採用。</p> <p>他の方法としては <code>with</code> を使う方法が考えられます。</p> <p>ただし、これもいくつか工夫が必要です。</p> <h2>Dart Sass での検証2 (失敗 / <code>@foward</code> ~ <code>with</code>)</h2> <p>安直に <code>with</code> を使おうかと考えましたが、構文的に <code>with</code> は <code>@use</code> でしか使えません。</p> <p>そのため、以下のような書き換えは不可です。</p> <h3 id="src/scss/foundation/_index.scss"><a href="#src%2Fscss%2Ffoundation%2F_index.scss">src/scss/foundation/_index.scss</a></h3> <pre><code class="scss">@forward "../assets/bootstrap/bootstrap" with ( /* with の中では use で読み込んだファイルのスコープは使えない */ $theme-colors: ( /* 上書き */ primary: #333, /* デフォルトにないカラーの追加 */ main: red, ), ); //bootstrap </code></pre> <h2 id="Dart Sass での検証3 (失敗 / ファイルスコープ)"><a href="#Dart+Sass+%E3%81%A7%E3%81%AE%E6%A4%9C%E8%A8%BC3+%28%E5%A4%B1%E6%95%97+%2F+%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97%29">Dart Sass での検証3 (失敗 / ファイルスコープ)</a></h2> <p><code>@use</code> とセットで使うということが分かったので、今度は <code>@use</code> で読み込んでいる場所で <code>with</code> を付けたそうと思いました。</p> <h3 id="src/scss/layout/_l-header.scss"><a href="#src%2Fscss%2Flayout%2F_l-header.scss">src/scss/layout/_l-header.scss</a></h3> <pre><code class="scss">@use "../foundation" as f with ( $theme-colors: ( /* 上書き */ primary: f.$own-color, /* デフォルトにないカラーの追加 */ main: f.$own-main-color, ), ); .l-header { .navbar-brand { &, &:link, &:visited { color: f.$own-main-color; } &:hover, &:active, &:focus { color: f.$own-main-color_l; } } } // 略 </code></pre> <p>ただし、このような既述をすると以下のエラーが発生します。</p> <pre><code class="bash">Error: src/scss/layout/_l-header.scss Error: There is no module with the namespace "f". ╷ 7 │ primary: f.$own-color, │ ^^^^^^^^^^^^^ ╵ src/scss/layout/_l-header.scss 7:18 @use src/scss/index.scss 8:1 root stylesheet </code></pre> <p><code>with</code> の中では、その直前で既述した名前空間はまだ使えません。</p> <p>「独自に定義したメインカラーでプライマリーカラーを上書きしたい」というケースが多いと思われるので、 <code>with</code> で上書きするときにメインカラーが変数で指定できないのは困ります。</p> <p>そこで、独自定義の変数読み込みと Bootstrap 4 の読み込み部分を分けることにしました。</p> <h2 id="最終形"><a href="#%E6%9C%80%E7%B5%82%E5%BD%A2">最終形</a></h2> <h3 id="ディレクトリ構造"><a href="#%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA%E6%A7%8B%E9%80%A0">ディレクトリ構造</a></h3> <pre><code class="bash"> / └ src/ ├ html/ │ └ index.html │ └ scss/ ├ assets/ │ └ bootstrap/ │ │ └ bootstrap/ │ │ └ 略 │ └ bootstrap.scss │ ├ foundation/ │ ├ _index.scss │ ├ _mixin.scss │ └ _variables.scss │ ├ global/ │ └ _index.scss # 追加 │ ├ layout/ │ ├ _l-footer.scss │ ├ _l-header.scss │ └ _l-main.scss │ ├ object/ │ ├ component/ │ │ └ 略 │ ├ project/ │ │ └ 略 │ └ utility/ │ └ 略 │ └ index.scss </code></pre> <h3 id="src/scss/foundation/_scss_variable.scss"><a href="#src%2Fscss%2Ffoundation%2F_scss_variable.scss">src/scss/foundation/_scss_variable.scss</a></h3> <p>先程まであった上書き用のコードは削除。</p> <h3 id="src/scss/foundation/_index.scss"><a href="#src%2Fscss%2Ffoundation%2F_index.scss">src/scss/foundation/_index.scss</a></h3> <pre><code class="scss">@forward "variables"; @forward "mixin"; </code></pre> <p>Bootstrap 4 を読み込む <code>@forward</code> を削除。</p> <h3 id="src/scss/global/_index.scss"><a href="#src%2Fscss%2Fglobal%2F_index.scss">src/scss/global/_index.scss</a></h3> <pre><code class="scss">@forward "../assets/bootstrap/bootstrap"; //bootstrap </code></pre> <p>Bootstrap 4 を読み込む部分を切り出したのを、 <code>src/scss/global/_index.scss</code> とします。</p> <h3 id="src/scss/layout/_l-header.scss"><a href="#src%2Fscss%2Flayout%2F_l-header.scss">src/scss/layout/_l-header.scss</a></h3> <pre><code class="scss">@use "../foundation" as f; @use "../global" as g with ( $theme-colors: ( /* 上書き */ primary: f.$own-color, /* デフォルトにないカラーの追加 */ main: f.$own-main-color, ), ); .l-header { .navbar-brand { &, &:link, &:visited { color: f.$own-main-color; } &:hover, &:active, &:focus { color: f.$own-main-color_l; } } } // 略 </code></pre> <p>実際に使う部分。変数は <code>foundation</code>, Bootstrap 4 は <code>global</code> で読み込み、 <code>foundation</code> を先に読み込むことで、 <code>with</code> の中で使用できるようにしました。</p> <h3 id="src/scss/index.scss"><a href="#src%2Fscss%2Findex.scss">src/scss/index.scss</a></h3> <pre><code class="scss">@use "layout/l-header"; @use "layout/l-main"; @use "layout/l-footer"; </code></pre> <p><code>index.css</code> になる部分は読み込みだけ。</p> <p>この形にすることでようやく当初意図していた形にすることができました。</p> <h2 id="備考1"><a href="#%E5%82%99%E8%80%831">備考1</a></h2> <p>今回の方法では Bootstrap 4 の中身は一切触れない方向で実装しました。そのため、 Bootstrap 4 の中は以前として <code>@import</code> で読み込まれており、変数はグローバルスコープに定義されるようです。</p> <p>そのため、今回は <code>src/scss/layout/_l-header.scss</code> でしか <code>with</code> を使用していませんが……</p> <p><a href="https://crieit.now.sh/upload_images/3415ce329faf1c572815489dd4a732555fc7a9865a365.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/3415ce329faf1c572815489dd4a732555fc7a9865a365.jpg?mw=700" alt="デフォルト状態のサンプル" /></a></p> <p>デフォルト状態ではこのような状態になります(プライマリーカラーがデフォルト、右側はデフォルト状態では存在しない <code>btn-main</code> クラスが付与されているため背景色なし)。</p> <p><a href="https://crieit.now.sh/upload_images/bf9bc07305297db9738d5598f4d950bd5fc7a98f8206f.jpg" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/bf9bc07305297db9738d5598f4d950bd5fc7a98f8206f.jpg?mw=700" alt="適用状態のサンプル" /></a></p> <p><code>src/scss/layout/_l-header.scss</code> に <code>with</code> を適用しただけで、メイン部分のボタンも影響を受けます。今回の場合は「全体で色を変更したい」のでこれで良いのですが、 <code>@use</code> や <code>@forward</code> の位置付けからすると役割を発揮できていない状態なので微妙なところ。</p> <p>今後、 Bootstrap が <code>@use</code>, <code>@forward</code> に変更した場合にこの辺りの挙動は変わると思われます。</p> <p>※ちなみに、v5.0.0-alpha3 でもまだ <code>@import</code> でした。</p> <h2 id="備考2"><a href="#%E5%82%99%E8%80%832">備考2</a></h2> <p>備考1と関連しますが、グローバルスコープに定義されるということは……</p> <h3 id="src/scss/layout/_l-header.scss"><a href="#src%2Fscss%2Flayout%2F_l-header.scss">src/scss/layout/_l-header.scss</a></h3> <pre><code class="scss">@use "../foundation" as f; @use "../global" as g; .l-header { .navbar-brand { &, &:link, &:visited { color: f.$own-main-color; } &:hover, &:active, &:focus { color: f.$own-main-color_l; } } } // 略 </code></pre> <p><code>src/scss/layout/_l-header.scss</code> は普通に <code>src/scss/global/_index.scss</code> を読み込み……</p> <h3 id="src/scss/layout/_l-main.scss"><a href="#src%2Fscss%2Flayout%2F_l-main.scss">src/scss/layout/_l-main.scss</a></h3> <pre><code class="scss">@use "../foundation" as f; @use "../global" as g with ( $theme-colors: ( /* 上書き */ primary: f.$own-color, /* デフォルトにないカラーの追加 */ main: f.$own-main-color, ), ); .l-main { background-color: f.$own-bg-color; color: f.$own-color; .btn-main { color: f.$own-color; } } // 略 </code></pre> <p><code>src/scss/layout/_l-header.scss</code> の後に読み込まれる <code>src/scss/layout/_l-main.scss</code> で <code>with</code> を使用した場合、以下のエラーが発生します。一度読み込んだモジュールが <code>with</code> 使用で再度読み込まれている、という旨のエラーですね。</p> <pre><code class="bash">Error: This module was already loaded, so it can't be configured using "with". ┌──> src/scss/layout/_l-main.scss 4 │ ┌ @use "../global" as g with ( 5 │ │ $theme-colors: ( 6 │ │ /* 上書き */ 7 │ │ primary: f.$own-color, 8 │ │ /* デフォルトにないカラーの追加 */ 9 │ │ main: f.$own-main-color, 10│ │ ), 11│ │ ); │ └─^ new load ╵ ┌──> src/scss/layout/_l-header.scss 4 │ @use "../global" as g; │ ━━━━━━━━━━━━━━━━━━━━━ original load ╵ src/scss/layout/_l-main.scss 4:1 @use src/scss/index.scss 9:1 root stylesheet Error: src/scss/layout/_l-main.scss Error: This module was already loaded, so it can't be configured using "with". ┌──> src/scss/layout/_l-main.scss 4 │ ┌ @use "../global" as g with ( 5 │ │ $theme-colors: ( 6 │ │ /* 上書き */ 7 │ │ primary: f.$own-color, 8 │ │ /* デフォルトにないカラーの追加 */ 9 │ │ main: f.$own-main-color, 10│ │ ), 11│ │ ); │ └─^ new load ╵ ┌──> src/scss/layout/_l-header.scss 4 │ @use "../global" as g; │ ━━━━━━━━━━━━━━━━━━━━━ original load ╵ src/scss/layout/_l-main.scss 4:1 @use src/scss/index.scss 9:1 root stylesheet </code></pre> <p>そのため、 <code>with</code> を使用するならば全体を通して <code>src/scss/global/_index.scss</code> が最初に <code>@use</code> で読み込まれる部分に既述する必要があります。</p> <hr /> <p>以上、知らないと全体的に嵌まり所が多い感じだったのでメモしておきます。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <h3 id="with"><a href="#with">with</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://www.boel.co.jp/tips/vol114/">Sassの新しいモジュールシステム | BOEL Inc. | ブランディング&デザインファーム</a></li> <li><a target="_blank" rel="nofollow noopener" href="https://kojika17.com/2020/05/next-generation-sass-module-system.html">Sassを@importから@useに置き換えるための手引き | Web Design KOJIKA17</a></li> </ul> <h3 id="今までのやり方 (参考)"><a href="#%E4%BB%8A%E3%81%BE%E3%81%A7%E3%81%AE%E3%82%84%E3%82%8A%E6%96%B9+%28%E5%8F%82%E8%80%83%29">今までのやり方 (参考)</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://homupedia.com/bootstrap4-how-to-customize-theme.html">Bootstrap4のテーマをカスタマイズする3つの簡単な方法 | ホムペディア</a></li> </ul> <h3 id="Bootstrap (v5.0.0-alpha3)"><a href="#Bootstrap+%28v5.0.0-alpha3%29">Bootstrap (v5.0.0-alpha3)</a></h3> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/twbs/bootstrap/tree/v5.0.0-alpha3">twbs/bootstrap at v5.0.0-alpha3</a></li> </ul> arm-band tag:crieit.net,2005:PublicArticle/14599 2018-11-12T00:32:00+09:00 2018-11-12T00:32:00+09:00 https://crieit.net/posts/Gulp-4-SCSS-Stylelint-Webpack-ESLint-Edge-js-BrowserSync Gulp 4 で SCSS + Stylelint + Webpack + ESLint + Edge.js + BrowserSync なフロントエンド環境構築 <p>(<a target="_blank" rel="nofollow noopener" href="https://www.hypertextcandy.com/gulp-4-frontend-development-starter/">ブログ</a>からのクロス投稿です。)</p> <p><img src="https://cdn.hypertextcandy.com/posts/gulp-4-frontend-development-starter/EyeCatch.jpg" alt="Eye catch" /></p> <p>この記事では、Gulp 4でフロントエンドの開発環境を構築する方法を紹介します。Gulp 4をタスクランナーとして、CSSのトランスパイルに SCSS + Stylelint、JavaScript のトランスパイルに Webpack + ESLint、、テンプレートエンジンとして Edge.js、さらにローカルサーバーとして BrowserSync を組み合わせます。</p> <p>私はどちらかというとサーバサイドな人でフロントエンド専門ではないのですが、モックアップ作ったりで HTML コーディングしたくなって、いまさらながら Gulp で自分なりの環境構築をしたので結果を共有します。</p> <p>フロントエンドと言っても全面的に React や Vue でゴリゴリアプリケーションを書くというより HTML コーディングの範疇内でのユースケースを想定しています(フレームワークでゴリゴリしたいなら <a target="_blank" rel="nofollow noopener" href="https://github.com/facebook/create-react-app">create-react-app</a> とか <a target="_blank" rel="nofollow noopener" href="https://cli.vuejs.org/">vue-cli</a> とか使うといいです)。</p> <h2 id="概要"><a href="#%E6%A6%82%E8%A6%81">概要</a></h2> <p>サンプルコードも含めた設定の全体については<a target="_blank" rel="nofollow noopener" href="https://github.com/MasahiroHarada/gulp-4-starter">こちらのリポジトリ</a>を参照してください。</p> <h3 id="依存パッケージ"><a href="#%E4%BE%9D%E5%AD%98%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8">依存パッケージ</a></h3> <p><a target="_blank" rel="nofollow noopener" href="https://github.com/MasahiroHarada/gulp-4-starter/blob/master/package.json">https://github.com/MasahiroHarada/gulp-4-starter/blob/master/package.json</a></p> <p>ちなみに開発環境は Node v10.7.0、npm v6.4.1 です。</p> <h3 id="ビルドコマンド"><a href="#%E3%83%93%E3%83%AB%E3%83%89%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89">ビルドコマンド</a></h3> <p>最終的なビルドコマンドは以下の通りです。</p> <pre><code class="console">// 開発ビルド:監視モードで実行されます。 $ npm run dev // 本番ビルド:JavaScript が圧縮されます。 $ npm run prod </code></pre> <h2 id="ビルドタスク"><a href="#%E3%83%93%E3%83%AB%E3%83%89%E3%82%BF%E3%82%B9%E3%82%AF">ビルドタスク</a></h2> <h3 id="gulpfile.babel.js"><a href="#gulpfile.babel.js">gulpfile.babel.js</a></h3> <p>ES Modules(import/export)を使用したかったのでファイル名に <code>.babel</code> をつけて Babel のトランスパイルがかかるようにしました。</p> <p>gulpfile.babel.js</p> <pre><code class="js">import { series, parallel, watch } from 'gulp'; import { reload, serve } from './tasks/server'; import { styles } from './tasks/styles'; import { scripts } from './tasks/scripts'; import { templates } from './tasks/templates'; import { images } from './tasks/images'; import { clean } from './tasks/clean'; import { sass as sassConfig, scripts as jsConfig, images as imagesConfig, templates as templatesConfig } from './tasks/config'; /** * ファイルの変更を監視 */ function watchFiles() { // Sass watch(sassConfig.src, series(styles, reload)); // Templates watch( [templatesConfig.edges, templatesConfig.data, templatesConfig.helper], series(templates, reload) ); // JavaScript watch(jsConfig.src, series(scripts, reload)); // Images watch(imagesConfig.src, series(images, reload)); } /** * 開発用ビルド */ export const dev = series( clean, parallel(styles, templates, scripts, images), serve, watchFiles ); /** * 本番用ビルド */ export const build = series( clean, parallel(styles, templates, scripts, images) ); </code></pre> <p>前述の通り gulpfile を ES2015 以降の構文で書くために Babel の設定ファイルも追加します。</p> <p>.babelrc</p> <pre><code class="json">{ "presets": [ [ "@babel/preset-env", { "targets": { "node": "current" } } ] ] } </code></pre> <p>タスクを色々書くと長くなってしまうので、個別のタスクはそれぞれ別ファイルに分け、<code>tasks</code> ディレクトリに格納しています。</p> <p>それぞれ見ていきましょう。</p> <h3 id="設定ファイル"><a href="#%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB">設定ファイル</a></h3> <p>まずは設定ファイルです。パスの設定が入っています。</p> <p>tasks/config.js</p> <pre><code class="js">const ASSET_ROOT = 'src'; const DEST_ROOT = 'public'; export const sass = { src: `${ASSET_ROOT}/sass/**/*.scss`, dest: `${DEST_ROOT}/styles` }; export const scripts = { srcRoot: `${ASSET_ROOT}/js`, src: `${ASSET_ROOT}/js/**/*.js`, dest: `${DEST_ROOT}/js`, babelrc: { presets: [['@babel/env', { targets: '> 0.25%, not dead' }]] } }; export const templates = { root: `${ASSET_ROOT}/templates`, edges: `${ASSET_ROOT}/templates/**/*.edge`, pages: `${ASSET_ROOT}/templates/pages/**/*.edge`, data: `${ASSET_ROOT}/templates/data.json`, helper: `${ASSET_ROOT}/templates/helper.js`, dest: DEST_ROOT }; export const images = { src: `${ASSET_ROOT}/images/**/*.*`, dest: `${DEST_ROOT}/images` }; export const isProd = process.env.NODE_ENV === 'production'; </code></pre> <h3 id="BrowserSync"><a href="#BrowserSync">BrowserSync</a></h3> <p>ファイルの変更を検知して自動でブラウザをリロードさせるため、<a target="_blank" rel="nofollow noopener" href="https://browsersync.io/">BrowserSync</a> のタスクを作成します。設定方法は<a target="_blank" rel="nofollow noopener" href="https://github.com/gulpjs/gulp/blob/4.0/docs/recipes/minimal-browsersync-setup-with-gulp4.md">こちら(Minimal BrowserSync setup with Gulp 4)</a>を参考にしました。</p> <p>tasks/server.js</p> <pre><code class="js">import browserSync from 'browser-sync'; const server = browserSync.create(); /** * 開発用サーバ再起動 */ export function reload(cb) { server.reload(); cb(); } /** * 開発用サーバ起動 */ export function serve(cb) { server.init({ server: { baseDir: './public' } }); cb(); } </code></pre> <h3 id="Clean"><a href="#Clean">Clean</a></h3> <p>ファイルの出力前に出力先の既存ファイルを削除しておくためのタスクです。</p> <p>tasks/clean.js</p> <pre><code class="js">import del from 'del'; /** * 出力先のディレクトリを空にする */ export function clean() { return del(['public']); } </code></pre> <h3 id="スタイル"><a href="#%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB">スタイル</a></h3> <p>スタイルに関しては2つのタスクを定義しています。</p> <p>まず1つめはSCSS を CSS に変換するためのタスクです。ソースマップ生成(<a target="_blank" rel="nofollow noopener" href="https://github.com/gulp-sourcemaps/gulp-sourcemaps">gulp-sourcemaps</a>)とファイル圧縮(<a target="_blank" rel="nofollow noopener" href="https://github.com/scniro/gulp-clean-css">gulp-clean-css</a>)も実行しています。</p> <p>2つめは CSS(今回は SCSS)の構文チェックツール <a target="_blank" rel="nofollow noopener" href="https://stylelint.io/">Stylelint</a> を実行するためのタスクです。<a target="_blank" rel="nofollow noopener" href="https://github.com/olegskl/gulp-stylelint">gulp-stylelint</a> を使用します。またファイルの監視中に毎回すべてのファイルを lint せず変更があったファイルのみチェックするために <a target="_blank" rel="nofollow noopener" href="https://github.com/alexgorbatchev/gulp-changed-in-place">gulp-changed-in-place</a> というプラグインも使用します。</p> <p>tasks/styles.js</p> <pre><code class="js">import gulp from 'gulp'; import gulpSass from 'gulp-sass'; import sourcemaps from 'gulp-sourcemaps'; import cleancss from 'gulp-clean-css'; import plumber from 'gulp-plumber'; import gulpStylelint from 'gulp-stylelint'; import changed from 'gulp-changed-in-place'; import { sass as config, isProd } from './config'; /** * SCSS -> CSS */ export function sass() { return gulp .src(config.src) .pipe(plumber()) .pipe(sourcemaps.init()) .pipe(gulpSass().on('error', gulpSass.logError)) .pipe(cleancss()) .pipe(sourcemaps.write('.')) .pipe(gulp.dest(config.dest)); } /** * Stylelint */ export function stylelint() { return gulp .src(config.src) // firstPass は初回実行時に全ファイルを対象とするかどうかのオプション .pipe(changed({ firstPass: true })) .pipe(gulpStylelint({ failAfterError: isProd, reporters: [{ formatter: 'verbose', console: true }], syntax: 'scss' })); } export const styles = gulp.series(stylelint, sass); </code></pre> <p>Stylelint の設定ファイルです。</p> <p>```json:.stylelintrc<br /> {<br /> "extends": "stylelint-config-standard",<br /> "plugins": ["stylelint-order"],<br /> "rules": {<br /> "order/properties-alphabetical-order": true<br /> }<br /> }</p> <pre><code><br />### 画像圧縮 [gulp-imagemin](https://github.com/sindresorhus/gulp-imagemin) を使って画像圧縮を行うタスクです。 オプションはお好みでどうぞ。 tasks/images.js ```js import gulp from 'gulp'; import imagemin from 'gulp-imagemin'; import { images as config } from './config'; export function images() { return gulp .src(config.src) .pipe(imagemin()) .pipe(gulp.dest(config.dest)); } </code></pre> <h3 id="Edge.js → HTML"><a href="#Edge.js+%E2%86%92+HTML">Edge.js → HTML</a></h3> <p>テンプレートエンジン <a target="_blank" rel="nofollow noopener" href="https://edge.adonisjs.com/">Edge.js</a> のファイルを HTML に変換するためのタスクです。</p> <p>Edge.js について詳しくは<a target="_blank" rel="nofollow noopener" href="https://www.hypertextcandy.com/build-frontend-with-edgejs">こちらの記事</a>もご覧ください。</p> <p>tasks/templates.js</p> <pre><code class="js">import gulp from 'gulp'; import edge from 'edge.js'; import tap from 'gulp-tap'; import rename from 'gulp-rename'; import fs from 'fs'; import path from 'path'; import { templates as config } from './config'; /** * Edge.js -> HTML */ export function templates() { // テンプレートを読み込む edge.registerViews(path.join(__dirname, `../${config.root}`)); // データファイルを読み込む const data = fs.existsSync(config.data) ? JSON.parse(fs.readFileSync(config.data, 'utf8')) : {}; // ヘルパー関数を読み込む fs.existsSync(config.helpers) && require(`../${config.helper}`); return gulp .src(config.pages) .pipe( tap(file => { const contents = edge.renderString(String(file.contents), data); file.contents = new Buffer(contents); }) ) .pipe(rename({ extname: '.html' })) .pipe(gulp.dest(config.dest)); } </code></pre> <h3 id="JavaScript"><a href="#JavaScript">JavaScript</a></h3> <p>タスク <code>esTranspile</code> は <a target="_blank" rel="nofollow noopener" href="https://www.npmjs.com/package/webpack-stream">Webpack</a> により JavaScript のトランスパイル〜バンドルを行います。</p> <p>また <code>esLint</code> タスクではコードのチェックのために <a target="_blank" rel="nofollow noopener" href="https://eslint.org/">ESLint</a> を実行します。<a target="_blank" rel="nofollow noopener" href="https://github.com/adametry/gulp-eslint">gulp-eslint</a> プラグインを使用します。</p> <p>tasks/scripts.js</p> <pre><code class="js">import gulp from 'gulp'; import gulpIf from 'gulp-if'; import plumber from 'gulp-plumber'; import gulpEslint from 'gulp-eslint'; import webpack from 'webpack'; import gulpWebpack from 'webpack-stream'; import changed from 'gulp-changed-in-place'; import { scripts as config, isProd } from './config'; export function esTranspile() { return gulp .src(config.src) .pipe(plumber()) // gulp.watch と一緒に使う場合は第二引数が必須らしい。 // https://www.npmjs.com/package/webpack-stream#usage-with-gulp-watch .pipe(gulpWebpack(require('../webpack.config.js'), webpack)) .pipe(gulp.dest(config.dest)); } export function esLint() { return gulp .src(config.src) .pipe(changed({ firstPass: true })) .pipe(gulpEslint()) .pipe(gulpEslint.format()) .pipe(gulpIf(isProd, gulpEslint.failAfterError())); } export const scripts = gulp.series(esLint, esTranspile); </code></pre> <p>Webpack の設定ファイルです。</p> <p>webpack.config.js</p> <pre><code class="js">import { scripts as config } from './tasks/config'; module.exports = { mode: process.env.NODE_ENV ? 'production' : 'development', entry: { app: `./${config.srcRoot}/app.js` }, module: { rules: [ { test: /\.js$/, use: 'babel-loader' } ] }, output: { filename: '[name].js', }, devtool: 'source-map' } </code></pre> <p>複数のファイルを出力したい場合は、以下のように <code>entry</code> に追記すれば OK です。</p> <pre><code class="js">entry: { app: `./${config.srcRoot}/app.js`, foo: `./${config.srcRoot}/foo.js` }, </code></pre> <p>こちらはESLint の設定ファイルです。</p> <p>.eslintrc</p> <pre><code class="json">{ "extends": ["eslint:recommended"], "parserOptions": { "ecmaVersion": 6, "sourceType": "module" }, "env": { "browser": true, "node": true } } </code></pre> <h3 id="フォーマッタ"><a href="#%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%82%BF">フォーマッタ</a></h3> <p>フォーマッタはオマケです。お好みの設定&エディタと連携していただければ。</p> <h4 id="EditorConfig"><a href="#EditorConfig">EditorConfig</a></h4> <p>.editorconfig</p> <pre><code class="ini">root = true [*] end_of_line = lf insert_final_newline = true [*.{html,edge,scss,css,js,svg}] indent_style = space indent_size = 2 </code></pre> <h4 id="Prettier"><a href="#Prettier">Prettier</a></h4> <p>.prettierrc</p> <pre><code class="json">{ "singleQuote": true } </code></pre> <p>以上です。参考になれば幸いです。</p> Masahiro Harada tag:crieit.net,2005:PublicArticle/14460 2018-05-31T18:41:24+09:00 2018-10-28T22:25:11+09:00 https://crieit.net/posts/68dc7de74ee7261f674d9b137a849942 フォントのアンチエイリアス設定 <p>webkitとfirefoxで記法が違って紛らわしいので備忘録</p> <pre><code class="sass">// フォントのアンチエイリアス =font-smoothing($type) @if $type == 'subpixel-antialiased' -webkit-font-smoothing: subpixel-antialiased -moz-osx-font-smoothing: unset @if $type == 'antialiased' -webkit-font-smoothing: antialiased -moz-osx-font-smoothing: grayscale </code></pre> naokazuterada