bootstrapのバージョンアップ

現時点ではまだbeta版なので、npmでバージョン指定をして更新します。

npm install --save bootstrap@v4.0.0-beta

popper.jsのインストール

bootstrap4はpopper.jsが必要です。

npm install --save popper.js

(.jsが付かない”popper”というnpmパッケージがあったりするので間違えないように。間違って.jsなしのをインストールしていてしばらくハマった)

webpackの設定を書き換える

webpack.config.vendor.jsの内容を変更して、popper.jsも処理されるようにします。

const nonTreeShakableModules = [
    (省略)
    'jquery',
    'popper.js'
];

44行目あたりにある、

new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable)

この行に、popper.jsの設定を追加します。

new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery', Popper: ['popper.js', 'default'] }), // Maps these identifiers to the jQuery package (because Bootstrap expects it to be a global variable)

完了

あとはwebpackでvendor関連を再構築したら完了です。

popper.jsやwebpackの変更をしない状態の場合、jQueryがどうとか、popperがないとかいうエラーが出ます。

あと、実行してみたらわかりますが、bootstrap4は3からだいぶ変わっているので、豪華なHelloWorldはちょっとおかしなことになります。もし3でなにか開発中の場合は全画面作り直すことは覚悟しないといけません。

webpackがまだいまいち把握できてないので、まだなんかいろんなところに手が届いてないような感覚が抜けません。さらにbootstrapだ、angularだと、調べないといけないことが多すぎてつらい。

環境的にVPNは欠かせないので、自分でさくらのVPSの一番安いやつで構築してます。CentOS7+xl2tpd+libreswanでL2TPというよくある構成です。
で、”万が一”が想定されるので、備えで常時二系統用意してあります。マスターはVPN専用ですが、バックアップは開発のテスト用サーバーなどに使っています。

が、ちょっとテスト用サーバーをクリーンな状態で再構築する必要があったのでしばらく前にOSからやりなおしたんですが、VPN環境をセットアップしてもVPNが繋がらなくなりました。接続は出来ていて通信が開始されたようなログになってるんですがそのあとすぐ切れてる様子。設定などは動いているものと同じなのでなんか間違ってるというわけではなさそう。

で、いろいろ設定見直したり、インストールしなおしたりしてたんですがだめだったんですが、まあバックアップ系統だったのでしばらく放置していたら、なんかマスターの方の接続が時々だめな状況に陥ることがあったので、バックアップをどうにかしないといけなくなりました。

もう一回全部やり直してマスターの設定と見直すんですが特に問題なく、八方ふさがり状態になったんですが、最後に気がついたのはxl2tpdのバージョンが上がってるということ。

マスターの方は1.3.6、新しくセットアップされていたのは1.3.8。

で、調べてみたら、

CentOS7のL2TP仕様が若干変わっていた

に、バージョンの違いで動作しなくなる話が出てました。
xl2tpdの設定で、crtsctsとlockがダメらしいのですが、確かに設定にそのオプションが入っていたので、コメントアウトしてみたらあっさりいけました。
確かに、セットアップ手順を書いているブログ記事などを見ていたらそのオプションが入ってないやつがあることは気がついていたのですが、さすがに自分の目の前で動いている設定だったのでそれを踏襲してました。

Visual Studioやdotnet newで作ることのできるAngularのプロジェクトは、最初からサーバーサイドレンダリングに対応したものが出来るのですが、慣れないうちは仕組みがよくわからなかったりとか、もっとシンプルな状態から理解を進めたいときにはややこしくて邪魔になりますので、その辺を削除してみます。

Views/Home/index.cshtml

<app asp-prerender-module="ClientApp/dist/main-server">Loading...</app>
↓
<app>Loading...</app>

実際はこれだけでサーバーサードレンダリングは行われなくなります。
まずは、main-serverがスタートすることでアプリケーションが始まるようになってるようで、クライアント側の準備が出来たら切り替わるんだと思います。

※これ以降は無理にやらなくてもいいんですが、そのままにしてしまうとなんか変な中途半端感がコードに残ってしまうので・・・

<script src="~/dist/main.js" asp-append-version="true"></script>

あとの作業用に、ここのファイル名も変えておきます。

webpack.config.js

32行目あたりのファイル名を変えます。

entry: { 'main-client': './ClientApp/boot.browser.ts' },
↓
entry: { 'main': './ClientApp/boot.ts' },

50,51行目あたりを書き換えます。

entryModule: path.join(__dirname, 'ClientApp/app/app.module.browser#AppModule'),
exclude: ['./**/*.server.ts']
↓
entryModule: path.join(__dirname, 'ClientApp/app/app.module#AppModule')

56行目あたりの下記部分をばっさり削除。

// Configuration for server-side (prerendering) bundle suitable for running in Node
const serverBundleConfig = merge(sharedConfig, {
(中略)
    target: 'node',
    devtool: 'inline-source-map'
});

最後の部分のserverに関する部分を削除。

return [clientBundleConfig, serverBundleConfig];
↓
return [clientBundleConfig];

webpackでサーバーサイド用のビルドをする部分ですね。

webpack.config.vendor.js

74行目あたりの下記部分をばっさり削除。

const serverBundleConfig = merge(sharedConfig, {
    target: 'node',
    resolve: { mainFields: ['main'] },
(中略)
            name: '[name]_[hash]'
        })
    ]
});

最後の部分のserverに関する部分を削除.

return [clientBundleConfig, serverBundleConfig];
↓
return [clientBundleConfig];

これも同様。

ClientAppディレクトリ以下

余計なファイルを削除して、ファイル名の変更等を行います。

削除

  • ClientApp/boot.server.ts
  • ClientApp/app/app.module.server.ts
  • ClientApp/distディレクトリ(もし既に実行していたら)

リネーム

  • ClientApp/boot.browser.ts → ClientApp/boot.ts
  • ClientApp/app/app.module.shared.ts → app.module.ts

ClientApp/app/app.module.ts

リネームしたshared.tsにapp.module.browser.tsの一部のコードをマージします。

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule } from '@angular/router';

import { AppComponent } from './components/app/app.component';
import { NavMenuComponent } from './components/navmenu/navmenu.component';
import { HomeComponent } from './components/home/home.component';
import { FetchDataComponent } from './components/fetchdata/fetchdata.component';
import { CounterComponent } from './components/counter/counter.component';

@NgModule({
    bootstrap: [AppComponent],
    declarations: [
        AppComponent,
        NavMenuComponent,
        CounterComponent,
        FetchDataComponent,
        HomeComponent
    ],
    imports: [
        BrowserModule,
        CommonModule,
        HttpModule,
        FormsModule,
        RouterModule.forRoot([
            { path: '', redirectTo: 'home', pathMatch: 'full' },
            { path: 'home', component: HomeComponent },
            { path: 'counter', component: CounterComponent },
            { path: 'fetch-data', component: FetchDataComponent },
            { path: '**', redirectTo: 'home' }
        ])
    ],
    providers: [
        { provide: 'BASE_URL', useFactory: getBaseUrl }
    ]
})
export class AppModule {
}

export function getBaseUrl() {
    return document.getElementsByTagName('base')[0].href;
}

そのあと、app.module.browser.tsは削除します。

ClientApp/app/boot.ts

import { AppModule } from './app/app.module.browser';
↓
import { AppModule } from './app/app.module';

マージしてしまっているので、app.moduleをimportするように修正します。

おわり

これでとりあえずサーバーサイドレンダリングを使っているようなところはあらかた消えてると思います。
削除できるモジュールがあると思うんですが、まだちょっとその辺は試してません。

何でこれやろうと思ったかというと、localStorageを使うようなコードがなんかうまく動かず、サーバーサイドで動いてるからだと気がつくまで結構ハマったからです。実際、作ろうとしているものも規模の小さいシンプルなものなので、ややこしい部分をなくしておきたかったと言うことで。
あと、これ動作するサーバーでnodeが使えないような状況では、サーバーサイドのコードは動かない気もします。

Webアプリケーション関連は、とにかく細かい技の組み合わせが多すぎて、なんか動くようなものを作るのに一苦労です。

Visual Studio 2017(15.2)でXamarinのiOSプロジェクトがビルドできない問題のもうちょっと根本的な解決方法です。

方法

C:\Program Files (x86)\Microsoft Visual Studio\2017(Edition)\MSBuild\Xamarin\Xamarin.Apple.Sdk.targetsを管理者権限のあるエディタで開いて、最後の方にあるPropertyGroupタグの間に、

$(TargetFrameworkRootPath)$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)

を追加します。

参考

56213 – Cannot build iOS App (Can not resolve reference: C:/Windows/Microsoft.NET/Framework/v4.0.30319/de/mscorlib.resources.dll)

のcomment 24

根本的な解決方法を追加しました。

概要

Visual Studio 2017が更新されバージョンが15.2になりましたが、このバージョンアップを行うと、XamarinのiOSプロジェクトがビルドでエラーになります。

エラーの要点は、

  • mscorlib.dll
  • mscorlib.resources.dll

の参照が解決できないというやつです。

Mac側でビルドする際に対象となるdllの各言語対応のものが送られてないのが原因のようです。

解決方法

エラーをよく確認すると、

C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/ja/mscorlib.dll

とか、参照しに行こうとしているdllのパスがあるはずなので、まずWindows側でそのファイルを探します。そのあと、Mac側で、

/Users/(user name)/Library/Caches/Xamarin/mtbs/builds/(project name)/(uuid)/C:/WINDOWS/Microsoft.NET/Framework/v4.0.30319/ja

に、Windowsからファイルをコピーしてやればビルドが通るようになります。
ディレクトリがない場合は作ってからファイルをコピーします。

雑記

WindowsのVisualStudioをバージョンアップする前に、Mac側にVisualStudio for Macをインストールしたり、Xamarin Studioをアンインストールしたりとごちゃごちゃしてたのでそのせいかと思っていろいろ試行錯誤してたんですが、Windows版のXamarinの問題だったようです。

参考

56213 – Cannot build iOS App (Can not resolve reference: C:/Windows/Microsoft.NET/Framework/v4.0.30319/de/mscorlib.resources.dll)

のcomment 12

« Prev Next »