web-dev-qa-db-ja.com

SapperのクライアントにのみFirebaseをインポートする方法は?

FirebaseをSapperアプリケーションにインポートしていますが、サーバーでインポートを評価したくありません。インポートがクライアント側のみであることを確認するにはどうすればよいですか?

私はSapperを使用して、静的ファイルを生成する_sapper export_を実行しています。私が試してみました:

  • 独自のファイルにfirebaseインスタンスを作成し、firebase.auth()およびfirebase.firestore()モジュールをエクスポートしました。

  • 以下のエラーメッセージから示唆されるように、rollup.config.jsを調整して依存関係を別の方法で解決しようとしています。これはより多くの頭痛をもたらします。

  • _client.js_でFirebaseインスタンスを作成します。失敗。

  • _stores.js_でインスタンスを作成します。失敗。

  • 変数を宣言し、onMount()で割り当てます。これにより、さまざまなブロックスコープで作業する必要があります。そして、少しハックを感じます。

アプリの初期化は正常に動作します:

_import firebase from 'firebase/app'

const config = {...}

firebase.initializeApp(config);
_

また、インポートを_import firebase from 'firebase'_だけに変更すると、このサーバーエラーが発生しないことも発見しました。

_ @firebase/app:
Warning: This is a browser-targeted Firebase bundle but it appears it is being run in a Node environment.  If running in a Node environment, make sure you are using the bundle specified by the "main" field in package.json.

If you are using Webpack, you can specify "main" as the first item in
"resolve.mainFields": https://webpack.js.org/configuration/resolve/#resolvemainfields

If using Rollup, use the rollup-plugin-node-resolve plugin and set "module" to false and "main" to true: https://github.com/rollup/rollup-plugin-node-resolve
_

これらのfirebase機能をファイルからエクスポートし、次のようにコンポーネントにインポートすることを期待しました

_<script>
  import { auth } from "../firebase";
</script>
_

しかし、そのインポートが含まれるとすぐに、開発サーバーがクラッシュします。静的ファイルを生成しているだけなので、サーバーで使用したくありません。

クライアント側でのみインポートを実現する方法について何かアイデアはありますか?

11
Eckhardt

だから私はこれに時間をかけすぎました。 onMOun​​tほど優れたソリューションはありません。

ただし、SapperはSSR機能に実際に使用する必要があることを理解しました。そして、Sapper SSRとCloud Functionsを使用してFirebaseで設定する方法に関する記事を書きました。

https://dev.to/eckhardtd/how-to-Host-a-sapper-js-ssr-app-on-firebase-hmb

元の質問に対する別の解決策は、src/template.htmlファイルを介してFirebase CDNをグローバルスコープに置くことです。

<body>
    <!-- The application will be rendered inside this element,
         because `app/client.js` references it -->
    <div id='sapper'>%sapper.html%</div>

    <!-- Sapper creates a <script> tag containing `app/client.js`
         and anything else it needs to hydrate the app and
         initialise the router -->
    %sapper.scripts%
      <!-- Insert these scripts at the bottom of the HTML, but before you use any Firebase services -->

  <!-- Firebase App (the core Firebase SDK) is always required and must be listed first -->
  <script src="https://www.gstatic.com/firebasejs/6.0.4/firebase-app.js"></script>

  <!-- Add Firebase products that you want to use -->
  <script src="https://www.gstatic.com/firebasejs/6.0.4/firebase-auth.js"></script>
  <script src="https://www.gstatic.com/firebasejs/6.0.4/firebase-firestore.js"></script>
</body>
</html>

そしてコンポーネント内:

<script>
import { onMount } from 'svelte';
let database, authentication;

onMount(() => {
  database = firebase.firestore();
  authentication = firebase.auth();
});

const authHandler = () => {
  if (process.browser) {
    authentication
    .createUserWithEmailAndPassword()
    .catch(e => console.error(e));
  }
}
</script>

<button on:click={authHandler}>Sign up</button>
7
Eckhardt

ES6を使用してFirebaseをインポートできました。ロールアップを使用している場合は、commonjsプラグインでnamedExportsを構成する必要があります。

//--- rollup.config.js ---
...
commonjs({
        namedExports: {
          // left-hand side can be an absolute path, a path
          // relative to the current directory, or the name
          // of a module in node_modules
          'node_modules/idb/build/idb.js': ['openDb'],
          'node_modules/firebase/dist/index.cjs.js': ['initializeApp', 'firestore'],
        },
      }),

あなたはこのようにそれを使うことができます:

//--- db.js ---
import * as firebase from 'firebase';
import 'firebase/database';
import { firebaseConfig } from '../config'; //<-- Firebase initialization config json

// Initialize Firebase
firebase.initializeApp(firebaseConfig);
export { firebase };
// Initialize db
export const db = firebase.firestore();

そしておそらくそのようなサービスでそれを使用します:

// --- userService.js ----
import { db } from './common';

const usersCol = db.collection('users');
export default {
  async login(username, password) {
    const userDoc = await usersCol.doc(username).get();
    const user = userDoc.data();
    if (user && user.password === password) {
      return user;
    }
    return null;
  },
};

[〜#〜] edited [〜#〜]完全なロールアップ構成

/* eslint-disable global-require */
import resolve from 'rollup-plugin-node-resolve';
import replace from 'rollup-plugin-replace';
import commonjs from 'rollup-plugin-commonjs';
import svelte from 'rollup-plugin-svelte';
import babel from 'rollup-plugin-babel';
import { terser } from 'rollup-plugin-terser';
import config from 'sapper/config/rollup';
import { sass } from 'svelte-preprocess-sass';
import pkg from './package.json';

const mode = process.env.NODE_ENV;
const dev = mode === 'development';
const legacy = !!process.env.SAPPER_LEGACY_BUILD;

// eslint-disable-next-line no-shadow
const onwarn = (warning, onwarn) =>
  (warning.code === 'CIRCULAR_DEPENDENCY' && warning.message.includes('/@sapper/')) || onwarn(warning);

export default {
  client: {
    input: config.client.input(),
    output: config.client.output(),
    plugins: [
      replace({
        'process.browser': true,
        'process.env.NODE_ENV': JSON.stringify(mode),
      }),
      svelte({
        dev,
        hydratable: true,
        emitCss: true,
        preprocess: {
          style: sass(),
        },
      }),
      resolve({
        browser: true,
      }),
      commonjs({
        namedExports: {
          // left-hand side can be an absolute path, a path
          // relative to the current directory, or the name
          // of a module in node_modules
          'node_modules/idb/build/idb.js': ['openDb'],
          'node_modules/firebase/dist/index.cjs.js': ['initializeApp', 'firestore'],
        },
      }),

      legacy &&
        babel({
          extensions: ['.js', '.mjs', '.html', '.svelte'],
          runtimeHelpers: true,
          exclude: ['node_modules/@babel/**'],
          presets: [
            [
              '@babel/preset-env',
              {
                targets: '> 0.25%, not dead',
              },
            ],
          ],
          plugins: [
            '@babel/plugin-syntax-dynamic-import',
            [
              '@babel/plugin-transform-runtime',
              {
                useESModules: true,
              },
            ],
          ],
        }),

      !dev &&
        terser({
          module: true,
        }),
    ],

    onwarn,
  },

  server: {
    input: config.server.input(),
    output: config.server.output(),
    plugins: [
      replace({
        'process.browser': false,
        'process.env.NODE_ENV': JSON.stringify(mode),
      }),
      svelte({
        generate: 'ssr',
        dev,
      }),
      resolve(),
      commonjs(),
    ],
    external: Object.keys(pkg.dependencies).concat(require('module').builtinModules || Object.keys(process.binding('natives'))),

    onwarn,
  },

  serviceworker: {
    input: config.serviceworker.input(),
    output: config.serviceworker.output(),
    plugins: [
      resolve(),
      replace({
        'process.browser': true,
        'process.env.NODE_ENV': JSON.stringify(mode),
      }),
      commonjs(),
      !dev && terser(),
    ],

    onwarn,
  },
};

4
Tiago Nobrega