Я застрял на некоторое время, пытаясь создать веб-пакет для моих файлов облачных функций.
Структура моего проекта:
ROOT
- FUNCTIONS
- DIS
- bundle.js // THIS SHOULD BE GENERATED BY WEBPACK
- SRC
- myCloudFunction.js // SOURCE CODE FOR A CLOUD FUNCTION
- entryPoint.js // ENTRY POINT FOR WEBPACK
- index.js
- package.json
- SRC
- App.js
.babelrc
firebase.json
webpack.prod.js // THIS BUILDS FOR CLIENT (WORKING FINE)
webpack.server.js // THIS SHOULD BUILD FOR THE SERVER (NOT WORKING)
Моя цельэто:
- Записать файлы облачных функций и
index.js
в современный JS, а также перенести и связать их с веб-пакетом (используя тот же webpack
, который я использую для связывания моего клиентского кода, но с другой конфигурациейфайл).
myCloudFunction.js (простая функция записи некоторого текста)
module.exports = (req,res) => {
console.log('myCloudFunction is executing...');
res.status(200).send('From myCloudFunction...');
}
entryPoint.js (в основном импортирует функциикод и экспортировать их как облачные функции)
const functions = require('firebase-functions');
const myCloudFunction = require('./src/myCloudFunction');
module.exports.myCloudFunction = functions.https.onRequest(myCloudFunction);
Если я сделаю index.js
точно так же, как мой entryPoint.js
, он будет работать просто отлично. Но я хочу связать файлы с помощью веб-пакета из entryPoint.js
и установить для связанного результата мой index.js
файл. В этом случае будут объединены только 2 файла (entryPoint
и myCloudFunction
).
Я использую для упаковки webpack:
webpack.prod.server.js
const webpack = require('webpack');
const path = require('path');
const Dotenv = require('dotenv-webpack');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const nodeExternals = require('webpack-node-externals');
module.exports = {
mode: 'development',
stats: 'verbose',
devtool: 'inline-source-map',
entry: {
app: './functions/src/entryPoint.js'
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, './functions/dist'),
publicPath: '/'
},
// externals: {
// "firebase-admin": true,
// "firebase-functions": true
// },
target: 'node',
externals: [nodeExternals(),'firebase-functions', 'firebase-admin','firebase'],
plugins:[
new CleanWebpackPlugin(),
new webpack.HashedModuleIdsPlugin(),
new webpack.DefinePlugin({
'process.env.ON_SERVER': true
}),
new Dotenv()
],
module: {
rules:[
{
test: /\.js$/,
include: path.resolve(__dirname, 'src'),
use: ['babel-loader']
},
]
}
};
Я читал, что вы не должны связывать node_modules с серверной частью, поэтому я использую свойство externals
.
bundle.js (пакет результатов после запуска webpack с конфигурацией выше)
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "oFca");
/******/ })
/************************************************************************/
/******/ ({
/***/ "4ouX":
/*!******************************************!*\
!*** ./functions/src/myCloudFunction.js ***!
\******************************************/
/*! no static exports found */
/***/ (function(module, exports) {
module.exports = (req,res) => {
console.log('myCloudFunction is executing...');
res.status(200).send('From myCloudFunction...');
}
/***/ }),
/***/ "O8Wp":
/*!*************************************!*\
!*** external "firebase-functions" ***!
\*************************************/
/*! no static exports found */
/***/ (function(module, exports) {
module.exports = firebase-functions;
/***/ }),
/***/ "oFca":
/*!********************************!*\
!*** ./functions/src/index.js ***!
\********************************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {
const functions = __webpack_require__(/*! firebase-functions */ "O8Wp");
const myCloudFunction = __webpack_require__(/*! ./myCloudFunction */ "4ouX");
module.exports.myCloudFunction = functions.https.onRequest(myCloudFunction);
/***/ })
/******/ });
ЭТО ДОЛЖНО БЫТЬ РАБОТАЕТ, НО Я ПОЛУЧАЮ ЭТУ ОШИБКУ:
Я быожидайте скопировать содержимое bundle.js
, вставить его в index.js
и заставить его работать. Но когда я делаю это, я получаю эту ошибку, когда пытаюсь выполнить функцию. См. Строку ошибки на рисунке ниже.
>>> firebase serve --only hosting,functions
+ functions: Using node@10 from host.
+ functions: Emulator started at http://localhost:5001
i functions: Watching "C:\Projects\test-ssr\functions" for Cloud Functions...
i hosting: Serving hosting files from: public
+ hosting: Local server: http://localhost:5000
! ReferenceError: firebase is not defined
at Object.O8Wp (C:\Projects\test-ssr\functions\index.js:110:20)
![enter image description here](https://i.stack.imgur.com/Xpcse.png)
ВОПРОС
Что я делаюнеправильно? Буду признателен за любую помощь!
ОБНОВЛЕНИЕ
Я только что обнаружил, что это решает проблему, но я понятия не имею, почему это необходимо. Мне все еще хотелось бы лучшего понимания этой проблемы.
webpack.prod.server.js
output: {
filename: '[name].[contenthash:5].js',
// filename: 'index.js',
path: path.resolve(__dirname, './functions/dist'),
publicPath: '/',
libraryTarget: 'commonjs' // <--- THIS FIXED IT
},