現象
有志でオープンソースで公開されているGitLabさんのHandbookを翻訳して日本語版立ち上げていますが。
こちらの https://gitlab.com/gitlab-com/www-gitlab-com/
からフォークして、ハンドブックのプレビューを起動すると
alias serve_handbook_faster="cd /home/workspaces/jp-www-gitlab-com/sites/handbook; NO_CONTRACTS=true bundle exec middleman serve"
serve_handbook_faster
と、ページ上部にエラーがでます
調査
インポートできていない?
該当箇所
@import "~be-navigation/dist/be-navigation";
:
チルダ ~
は node_modules
配下をみるエイリアスです
resolve: {
modules: [
"node_modules"
]
},
webpack.config.js
に resolve.modules
が定義されているので問題ないようです
$ ls node_modules/be-navigation/dist/
be-navigation.css be-navigation.umd.min.js
ちなみに be-navigation
は、Navigation for https://about.gitlab.com です
webpackの動作をチェック
"scripts": {
"start-webpack": "NODE_ENV=development npx webpack serve",
"build-webpack": "NODE_ENV=production npx webpack --bail --progress",
$ NODE_ENV=development npx webpack serve
ℹ 「wds」: Project is running at http://0.0.0.0:4567/
ℹ 「wds」: webpack output is served from /
ℹ 「wds」: Content not from webpack is served from /home/workspaces/jp-www-gitlab-com
ℹ 「wdm」: assets by path javascripts/ 109 MiB
assets by path javascripts/*.js 106 MiB 276 assets
assets by path javascripts/libs/*.js 2.25 MiB 37 assets
assets by path javascripts/applications/*.js 1.08 MiB
asset javascripts/applications/search_bar.js 372 KiB [emitted] (name: applications/search_bar)
asset javascripts/applications/broken_image_placeholder.js 366 KiB [emitted] (name: applications/broken_image_placeholder)
asset javascripts/applications/categories_scroller.js 366 KiB [emitted] (name: applications/categories_scroller)
assets by path stylesheets/*.css 3.54 MiB 188 assets
runtime modules 234 KiB 1248 modules
orphan modules 443 bytes [orphan] 1 module
code generated modules 3.43 MiB (javascript) 3.54 MiB (css/mini-extract) [code generated]
modules by path ./source/ 1.11 MiB (javascript) 3.54 MiB (css/mini-extract)
cacheable modules 1.11 MiB
modules by path ./source/stylesheets/*.scss 809 KiB 377 modules
modules by path ./source/javascripts/ 260 KiB 85 modules
modules by path ./source/frontend/ 72.2 KiB 41 modules
css modules 3.54 MiB
modules by path ./source/stylesheets/*.scss 3.02 MiB 188 modules
modules by path ./source/stylesheets/*.scss (1) 525 KiB
css ./node_modules/css-loader/dist/cjs.js??clonedRuleSet-1[0].rules[0].use[2]!./node_modules/sass-loader/dist/cjs.js!./source/stylesheets/2022-blog-refresh.css.scss (1) 6.43 KiB [code generated]
css ./node_modules/css-loader/dist/cjs.js??clonedRuleSet-1[0].rules[0].use[2]!./node_modules/sass-loader/dist/cjs.js!./source/stylesheets/be-navigation.css.scss (1) 518 KiB [code generated]
modules by path ./node_modules/ 2.31 MiB 214 modules
external "jQuery" 42 bytes [built] [code generated]
webpack 5.16.0 compiled successfully in 10128 ms
ℹ 「wdm」: Compiled successfully.
http://127.0.0.1:4567/stylesheets/be-navigation.css
にアクセスすると@importは解決されて正しく scss は css にコンパイルされていました
しかし serve_handbook_faster
で middleman経由で http://127.0.0.1:7654/stylesheets/be-navigation.css
にアクセスすると
/*
SassC::SyntaxError: Error: File to import not found or unreadable: ~be-navigation/dist/be-navigation.
on line 1:1 of ../../source/stylesheets/be-navigation.css.scss
>> @import "~be-navigation/dist/be-navigation";
^
Backtrace:
/home/workspaces/jp-www-gitlab-com/source/stylesheets/be-navigation.css.scss:1
/home/workspaces/jp-www-gitlab-com/vendor/bundle/ruby/3.0.0/gems/sassc-2.4.0/lib/sassc/engine.rb:50:in `render'
/home/workspaces/jp-www-gitlab-com/vendor/bundle/ruby/3.0.0/gems/middleman-core-4.4.2/lib/middleman-core/renderers/sass.rb:55:in `evaluate'
/home/workspaces/jp-www-gitlab-com/vendor/bundle/ruby/3.0.0/gems/tilt-2.0.10/lib/tilt/template.rb:109:in `render'
/home/workspaces/jp-www-gitlab-com/vendor/bundle/ruby/3.0.0/gems/middleman-core-4.4.2/lib/middleman-core/file_renderer.rb:79:in `render'
/home/workspaces/jp-www-gitlab-com/vendor/bundle/ruby/3.0.0/gems/middleman-core-4.4.2/lib/middleman-core/template_renderer.rb:184:in `_render_with_all_renderers'
/home/workspaces/jp-www-gitlab-com/vendor/bundle/ruby/3.0.0/gems/middleman-core-4.4.2/lib/middleman-core/template_renderer.rb:147:in `block in render'
:
/home/workspaces/jp-www-gitlab-com/vendor/bundle/ruby/3.0.0/gems/webrick-1.7.0/lib/webrick/server.rb:310:in `block in start_thread'
*/
body:before {
white-space: pre;
font-family: monospace;
content: "SassC::SyntaxError: Error: File to import not found or unreadable: ~be-navigation/dist/be-navigation.\A on line 1:1 of ../../source/stylesheets/be-navigation.css.scss\A >> @import \"~be-navigation/dist/be-navigation\";\A \A ^\A "; }
middlemanが正しく動いていない可能性が見えてきました
middlemanの調査
:
# External Pipeline
unless ENV['SKIP_EXTERNAL_PIPELINE']
# NOTE: if we use the external pipeline, we set the Middleman port to 7654,
# which the webpack devServer config relies on in webpack.config.js in the project root.
# We set up webpack devServer on port 4567 to keep the local dev commands the same,
# but it proxies to 7654 for everything other than the webpack assets.
# See doc/webpack.md for more information.
set(:port, 7654)
# This Middleman extension logs a custom message about the Webpack proxy port
activate :proxy_server_information
# NOTE: This only applies to 'development' mode. For local builds, use the `rake build:*` tasks
# NOTE: This runs webpack and makes assets available during local development
activate :external_pipeline,
name: :webpack,
command: "cd #{monorepo_root} && yarn run start-webpack",
source: "#{monorepo_root}/tmp/dist",
latency: 3
end
:
middleman 経由でプレビューを起動した場合(serve_handbook_faster
)は webpack
が動いていない?という検証をする。
http://127.0.0.1:4567/stylesheets/be-navigation.css
にアクセスすると正しく動作
http://127.0.0.1:7654/stylesheets/be-navigation.css
にアクセスすると正しく動作しない
という感じです
middlemanの機能やconfig.rbを確認する限り、middlemanにはwebpackへプロキシーする機能はないようです
起動時のメッセージの確認
英語
== Webpack proxy server enabled: use "http://localhost:4567" or "http://127.0.0.1:4567"
== Please ignore the following two lines - they will be missing necessary assets.
== View your site at "http://localhost:7654", "http://127.0.0.1:7654"
== Inspect your site configuration at "http://localhost:7654/__middleman", "http://127.0.0.1:7654/__middleman"
日本語訳
== Webpackのプロキシサーバーを有効にしました: "http://localhost:4567" or "http://127.0.0.1:4567" を使ってください
== 下記二行は無視してください - 下記では必要なアセットにアクセスできません
== サイトの閲覧はこちらから "http://localhost:7654", "http://127.0.0.1:7654"
== サイトの設定はこちらから "http://localhost:7654/__middleman", "http://127.0.0.1:7654/__middleman"
さらに webpack.md の確認
docs/webpack.md というドキュメントを確認しました
以下翻訳文
### DevServerとMiddlemanの使用
[Middleman external pipeline](https://middlemanapp.com/advanced/external-pipeline/) を使うと、WebpackをMiddlemanのビルドステップに統合することができます。これは Middleman の個々の設定ファイルで行われます。
* `sites/uncategorized/config.rb`
* `sites/handbook/config.rb`
デフォルトでは、前記のように外部パイプラインを追加すると、Webpack の出力を Middleman [サイトマップ](https://middlemanapp.com/advanced/sitemap/)に追加します。 書き出し先のディレクトリを指定する必要があります。Webpack のバンドルが変わると、Middlemanサーバがサイト全体を再構築して、Webpack も再構築する設定にしていると開発モードでは不要であり、時間もかかります。
さらに、Middleman は外部パイプラインをディスク上のディレクトリに向ける必要があるので、[Watch モード](https://webpack.js.org/guides/development/#using-watch-mode)でしか動作しません。実際にディスクに書き込むからですが、 devServer はそうではありません。
Middleman は `source/javascripts` と `source/stylesheets` ディレクトリを暗黙のうちにサイトマップに追加していることも、このプロセスを難しくしています。そのため、そこに変更を加えると、Webpack の再構築と同様に再構築のトリガーとなります(したがって、Webpack の出力がもう一度変わるのを見ながら Middleman を 3 回目の再構築を行います)。
つまり、Webpackで処理されるファイルについては、 **webpack、そしてwebpackだけ** に処理させ、Middlemanにはコードベース内のURLへの参照以外、何も知らせないようにしたいのです。
そこで、Middleman に `source/javascripts` と `source/stylesheets` ディレクトリのサイトマップの暗黙構築を無視するように設定することにします。
```rb
# sites/handbook/config.rb, sites/uncategorized/config.rb, any other config
# ...
ignore 'javascripts/*'
ignore 'stylesheets/*'
# ...
```
そして、外部パイプラインがwebpackを使うように設定し、`/tmp/dist`を指定します。この場所は、ウォッチモードを使う場合、webpackがファイルを書き込む**はずの**場所ですが、devServerが処理する間は静止していなければなりません。
```rb
# ...
activate :external_pipeline,
name: :webpack,
command: "cd #{monorepo_root} && yarn run start-webpack",
source: "#{monorepo_root}/tmp/dist",
latency: 3
# ...
```
この段階では、devServer はすべての webpack ファイルを管理しており、Middleman はそれらについて何も知りません。しかしそのため、Middleman のサーバプロセスからインメモリで **見えません**。
devServer と Middleman サーバーを同じポートにバインドすることはできませんし、アセットがリポジトリに分散しているため、開発モード用に `webpack-server-address:webpack-port/javascripts` と `webpack-server-address:webpack-port/stylesheets` などにポイントすることは広範囲かつ難しい変更でしょう。もし、参照を整理して、Webpacksの出力をすべてバンドルすれば、そのようなことができるようになります。
しかし、開発環境を同じにするために、[devServer proxy](https://webpack.js.org/configuration/dev-server/#devserverproxy) を使い、devServer を通して Middleman に *全てを* プロキシします、こんな感じです。
```js
devServer: {
index: '',
port: 4567,
proxy: {
'/': 'http://localhost:7654'
}
}
```
結論
MiddlemanからWebpackを起動するが、MiddlemanからWebpackがコンパイルしたアセットにアクセス(Proxy)するのは難しいため、アクセスする際は、Webpack側のdevServerからアクセスしてMiddlemanへアクセスするようにということでした