60038


# 知りたいこと

rollup.jsで、bundle（？）したJSが、HTML側の`<script>タグ`から読み込めるものと読み込めないものがある理由と、その解決方法。

# 環境

  * rollup.js v1.25.2
  * yarn 1.10.0
  * windows10

# やっていること

[leaflet](https://leafletjs.com/)を使いたいと思っております。  
leaflet本体はbundleされたJSファイルを`<script>`タグで呼び出せば使えますが、  
leafletのプラグインは呼び出すことができません。

設定ファイルを以下に記載します。

* * *

rollup.config.js

[code]

    import nodeResolve from 'rollup-plugin-node-resolve';
    import commonjs from 'rollup-plugin-commonjs';
    import babel from 'rollup-plugin-babel';
    import postcss from 'rollup-plugin-postcss';
    import cssnext from 'postcss-cssnext';                      // CSSを最新の記法に変換をかけるプラグイン
    
    export default {
        // コンパイル対象JSファイル
        input: './resources/js/app.js',
    
        // コンパイル済みJSファイルの書き出し先
        output: {
            format: 'iife',
            file: './public/js/bundle.js',
        },
    
        // コンパイルに利用するオプションと外部プラグイン
        plugins: [
            nodeResolve({jsnext: true}), // npmモジュールを`node_modules`から読み込む
            commonjs(), // CommonJSモジュールをES6に変換
            babel(), // ES5に変換
    
            // CSSのコンパイルと書き出し先を指定
            postcss({
                extensions: ['.css', '.sss'],
                extract: './public/css/main.css',
                plugins: [
                    cssnext({
                        calc: false,
                        rem: false,
                    }),
                ],
            }),
        ]
    }
    
[/code]

* * *

app.js

[code]

    import 'leaflet'
    import 'leaflet-geosearch'
    import 'leaflet/dist/leaflet.css';
    
[/code]

* * *

HTML

[code]

    <!-- JSとCSSの読み込み -->
    <link rel="stylesheet" href="/css/main.css">
    <script src="/js/bundle.js"></script>
    
    <!-- MAP表示エリア -->
    <div id="map" style="height: 450px;"></div>
    
    <!-- leafletjsの実行 -->
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <script>
        $(function () {
            let mymap = L.map('map').setView([35.68, 139.76], 13);
    
            L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', {
                maxZoom: 18
            }).addTo(mymap);
    
            // 住所をgeometryに変換するプラグイン
            const provider = new OpenStreetMapProvider();
    
            provider
                .search({ query: '京都市' })
                .then(function(result) {
                    console.log(result);
                });
        });
    </script>
    
[/code]

* * *

上記HTMLをブラウザで呼ぶと、

> ReferenceError: OpenStreetMapProvider is not defined

と表示されます。

`OpenStreetMapProvider`は[leaflet-
geosearchの公式](https://github.com/smeijer/leaflet-geosearch)の通り書いています。  
なので、おそらくrollup側でうまくコンパイルできていないのかと思いますが……

bundle.jsの中身を検索かけてみると、確かに存在します。

## ↓

##
[![画像の説明をここに入力](https://i.stack.imgur.com/RM1lA.jpg)](https://i.stack.imgur.com/RM1lA.jpg)

これはなぜなのでしょうか？

試しにapp.jsでimportではなくrequireを使ってみましたがエラーが増えた（requireは使えないというエラーが）だけでした。

* * *

また、むしろ定義のされていない `let mymap = L.map('map').setView([35.68, 139.76], 13);`
の`L`が使えるのも意味がわかりません。

このあたり詳しい方がいらっしゃいましたらご教示いただけますと幸いです。


CC BY-SA 4.0
2019-10-28T02:10:51.250
60032
2019-10-29T02:54:22.690
2019-10-29T02:54:22.690
32986
31257
question
javascript rollupjs
rollup.jsでbundleしたjsで、<script>から読み込めるものと読み込めないものの違い


ESモジュールを使う形で使う場合は、モジュールを使うコードもrollupで処理しますが、rollupでバンドルする場合、leafletやleaflet-
geosearchのESモジュール対応がまちまちのため本質的なところ以外で若干複雑になります。

app.js

[code]

    import { map, tileLayer } from 'leaflet'
    import { OpenStreetMapProvider } from 'leaflet-geosearch'
    
    export function init() {
        let mymap = map('map').setView([35.68, 139.76], 13);
    
        tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png', {
            maxZoom: 18
        }).addTo(mymap);
    
        // 住所をgeometryに変換するプラグイン
        const provider = new geosearch.OpenStreetMapProvider();
    
        provider
            .search({ query: '京都市' })
            .then(function(result) {
                console.log(result);
            });
    }
    
[/code]

ところが `leaflet@1.5.1` ではesm形式のファイルで提供されているのにも関わらず、 `package.json` の `module` や
`jsnext:main` で指定していないので rollup が dist/leaflet-src.esm.js
を見つけられません。そこで解決用のプラグインを追加します。  
また`rollup-plugin-
commonjs`が`OpenStreetMapProvider`を見つけられないの`namedExports`オプションで対応します。

rollup.config.js

[code]

    import nodeResolve from 'rollup-plugin-node-resolve';
    import commonjs from 'rollup-plugin-commonjs';
    import babel from 'rollup-plugin-babel';
    
    function resolveLeaflet() {
        return {
          name: 'resolve-leaflet',
          resolveId ( source ) {
            if (source === 'leaflet') {
                return {id: 'node_modules/leaflet/dist/leaflet-src.esm.js'};
            }
            return null;
          }
        };
    }
    
    export default {
        // コンパイル対象JSファイル
        input: './resources/js/app.js',
    
        // コンパイル済みJSファイルの書き出し先
        output: {
            format: 'iife',
            name: 'myapp',
            file: './public/js/bundle.js',
        },
    
        // コンパイルに利用するオプションと外部プラグイン
        plugins: [
            resolveLeaflet(),
            nodeResolve({jsnext: true}), // npmモジュールを`node_modules`から読み込む
            commonjs({ // CommonJSモジュールをES6に変換
                namedExports: {
                    'leaflet-geosearch': ['OpenStreetMapProvider']
                }
            }),
            babel(), // ES5に変換
        ]
    }
    
[/code]

最後にHTML側からはexportした関数を使います。

index.html

[code]

    <!-- JSとCSSの読み込み -->
    <link rel="stylesheet" href="css/main.css">
    <script src="js/bundle.js"></script>
    
    <!-- MAP表示エリア -->
    <div id="map" style="height: 450px;"></div>
    
    <!-- leafletjsの実行 -->
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
    <script>
        $(function () {
            myapp.init();
        });
    </script>
    
[/code]


CC BY-SA 4.0
2019-10-28T06:05:08.607
60038
2019-10-28T06:05:08.607
241
60032
answer