如何导入firebase并使用webpack将其服务分割成多个分割块?

f87krz0w  于 2023-10-19  发布在  Webpack
关注(0)|答案(2)|浏览(144)

我现在正在做的是:
firebase.js

import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import 'firebase/functions';
import 'firebase/storage';

const config = {
  apiKey: process.env.FIREBASE_APP_API_KEY,
  authDomain: process.env.FIREBASE_APP_AUTH_DOMAIN,
  databaseURL: process.env.FIREBASE_APP_DATABASE_URL,
  projectId: process.env.FIREBASE_APP_PROJECT_ID,
  storageBucket: process.env.FIREBASE_APP_STORAGE_BUCKET,
  messagingSenderId: process.env.FIREBASE_APP_MESSAGING_SENDER_ID,
  appId: process.env.FIREBASE_APP_ID,
};

firebase.initializeApp(config);

export default firebase;

webpack.config.js

optimization: {
  runtimeChunk: 'single',
  splitChunks: {
    chunks: 'all',
    maxInitialRequests: Infinity,
    minSize: 0,
    cacheGroups: {
      vendor: {
        test: /[\\/]node_modules[\\/]/,
        name(module) {
          const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
          return `npm.${packageName.replace('@', '')}`;
        },
      },
    },
  },
}

我从这篇文章中得到的webpack部分:
https://medium.com/hackernoon/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758
这就产生了这个小的667kbJS文件(这是生产版本):

问题

我可以用其他方式导入它,这样我就可以得到更小的块吗?
举例来说:

import firebase from 'firebase/app';
import auth from 'firebase/auth';
import firestore from 'firebase/firestore';
import functions from 'firebase/functions';
import storage from 'firebase/storage';

但我不知道要如何处理这些“额外对象”,因为我需要和使用的唯一对象是从firebase/app获得的firebase对象
另外,如果我像这样导入它们而不使用对象,Webpack不会将它们解释为“死代码”并对它们进行树摇吗?
什么是正确的方法来做这件事?

nxagd54h

nxagd54h1#

Firebase将这些导入直接加载到firebase对象中,没有办法从那里对它们进行treeshake。你可以做的是选择性地使用动态导入加载这些,然后webpack会处理这些代码。如果没有导入,这些示例不会被添加到firebase对象中,所以你可以做一个简单的if检查来加载它们。

export async function getFirestoreInstance() {
    if (!firebase.firestore) {
        await import('firebase/firestore');
    }

    return firebase.firestore();
}

例如,当您需要使用Firestore时,只需调用getFirestoreInstance

async function doSomethingWithFirestore(){
   try {
      const firestore = await getFirestoreInstance();
      firestore.collection("foo") // do something with firestore
   }
}
mv1qrgav

mv1qrgav2#

你应该使用我的配置。这些配置稍微减少了编译文件的大小。
webpack.config.js

const path = require("path");
const fs = require("fs");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = process.env.NODE_ENV !== "production";

/**
 * @type {import('webpack').Configuration}
 */
module.exports = {
    /**
     * The entry point file
     * [prevent duplication docs](https://webpack.js.org/guides/code-splitting/#prevent-duplication)
     */
    entry: {
        // shared utility
        shared: {
            import: ["bluebird", "crypto-js"],
        },
        // main script
        index: {
            import: "./src/index.js",
            dependOn: ["shared", "firebase", "internal"],
        },
        // all imported firebase module
        firebase: {
            import: ["firebase/app", "firebase/auth"],
            dependOn: "shared",
        },
        // internal/local utility
        internal: {
            import: ["./src/utils/index.ts"],
            dependOn: "shared",
        },
    },
    /**
     * The location of the build folder
     */
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "[name].[contenthash].js",
        chunkFilename: "[name].[contenthash].js",
    },
    /**
     * Prevent duplication
     * [docs](https://webpack.js.org/guides/code-splitting/#prevent-duplication)
     */
    optimization: {
        runtimeChunk: "single",
        splitChunks: {
            chunks: "all",
            cacheGroups: {
                styles: {
                    name: "styles",
                    type: "css/mini-extract",
                    chunks: "all",
                    enforce: true,
                },
            },
        },
    },
    // Optional and for development only. This provides the ability to
    // map the built code back to the original source format when debugging.
    devtool: "eval-source-map",
    module: {
        rules: [
            {
                test: /\.(ts|tsx)$/,
                use: "ts-loader",
                exclude: /node_modules|.test.(ts|js)$/,
            },
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: {
                    loader: "babel-loader",
                    options: {
                        presets: ["@babel/preset-env", "@babel/preset-react"],
                    },
                },
            },
            {
                test: /\.css$/,
                use: [
                    // Creates `style` nodes from JS strings
                    devMode ? "style-loader" : MiniCssExtractPlugin.loader,
                    // Translates CSS into CommonJS
                    "css-loader",
                ],
            },
            {
                test: /\.s[ac]ss$/i,
                use: [
                    // Creates `style` nodes from JS strings
                    devMode ? "style-loader" : MiniCssExtractPlugin.loader,
                    // Translates CSS into CommonJS
                    "css-loader",
                    // Compiles Sass to CSS
                    {
                        loader: "sass-loader",
                        options: {
                            // Prefer `dart-sass`
                            implementation: require("node-sass"),
                            sassOptions: {
                                includePaths: [
                                    path.join(__dirname, "../node_modules"),
                                    path.join(process.cwd(), "node_modules"),
                                    path.join(__dirname, "../../node_modules"),
                                ]
                                    .filter(fs.existsSync)
                                    .map((str) => path.resolve(str))
                                    .filter(function (elem, index, self) {
                                        return index === self.indexOf(elem);
                                    }),
                            },
                        },
                    },
                ],
            },
        ],
    },
    resolve: {
        extensions: [".*", ".ts", ".js", ".jsx"],
    },
    plugins: [
        new MiniCssExtractPlugin({
            // Options similar to the same options in webpackOptions.output
            // both options are optional
            filename: devMode ? "[name].css" : "[name].[contenthash].css",
            chunkFilename: devMode ? "[id].css" : "[id].[contenthash].css",
        }),
    ],
    /**
     * [Docs](https://webpack.js.org/configuration/dev-server/)
     * @type {import('webpack-dev-server').Configuration}
     */
    devServer: {
        //static: path.resolve(__dirname, './public'),
        historyApiFallback: true, // enable react-dom-router support
        hot: true, // hot reloading
        port: 4000,
        open: false,
    },
};

我的脚本package.json

{
  "scripts": {
    "start": "webpack-dev-server --no-open --mode development --config webpack.config.js",
    "prod:update": "cd page && npx npm-check-updates -u && npm install --omit=dev --production"
  }
}

相关问题