Как импортировать Firebase только на клиенте в Sapper? - PullRequest
3 голосов
/ 26 мая 2019

Я импортирую Firebase в свое приложение Sapper, я не хочу, чтобы импорт оценивался на сервере. Как мне убедиться, что импорт выполняется только на стороне клиента?

Я использую Sapper для запуска sapper export, который генерирует статические файлы. Я пробовал:

  • Создание экземпляра firebase в собственном файле и экспорт модулей firebase.auth() и firebase.firestore().

  • Попытка настроить файл rollup.config.js, чтобы разрешить зависимости по-разному, как предлагается из сообщения об ошибке ниже. Это приносит больше головной боли.

  • Создание экземпляра Firebase в client.js. Неудачный.

  • Создание экземпляра в 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>

Но как только этот импорт включается, сервер dev падает. Я не хочу использовать его на сервере, так как я просто генерирую статические файлы.

У кого-нибудь есть идеи, как добиться импорта только на стороне клиента?

Ответы [ 2 ]

3 голосов
/ 27 мая 2019

Так что я потратил слишком много времени на это. На самом деле нет более элегантного решения, чем onMOunt.

Тем не менее, я понял, что сапер действительно должен использоваться для его возможностей SSR. И я написал статью о том, как настроить Firebase с помощью Sapper SSR и облачных функций:

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

Другое решение оригинального вопроса - поместить CDN Firebase в глобальную область с помощью файла src/template.html.

<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>
0 голосов
/ 29 июня 2019

Мне удалось импортировать FireBase, используя ES6. Если вы используете накопительный пакет, вам нужно сконфигурировать namedExports в плагине commonjs:

//--- 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;
  },
};

...