McFree
@McFree
JS, TS, C#

Как через webpack можно собрать Adminjs сервис?

Пробовал собирать adminjs приложение, которое подтягивает зависимости из родительского node_modules.

{
  "name": "@cs/admin",
  "main": "index.ts",
  "scripts": {
    "build:dev": "webpack --config ../../webpack/admin.config.js --node-env development",
    "build:prod": "webpack --config ../../webpack/admin.config.js --node-env production",
    "start": "ts-node index.ts"
  },
  "dependencies": {
    "@adminjs/express": "^5.1.0",
    "@adminjs/passwords": "^3.0.1",
    "@adminjs/sequelize": "^3.0.0",
    "adminjs": "^6.8.3",
    "stream-http": "^3.2.0",
    "express-formidable": "^1.2.0",
    "express-session": "^1.17.3",
    "pg": "^8.9.0"
  },
  "devDependencies": {
    "node-loader": "^2.0.0"
  }
}


Структура выглядит так:
- node_modules
- - | ...
- - | adminjs
- - | @adminjs
- - - | design-system
- - - | passwords
- - - | sequelize
- package.json
- webpack
- | admin
- | admin.config.js
- | variables.js
- src
- | admin
- - | node_modules
- - - | path-to-regexp
- - - | @adminjs
- - - - | express
- - | index.ts
- - | package.json


package.json в src/admin:
{
  "name": "@cs/admin",
  "main": "index.ts",
  "scripts": {
    "build:dev": "webpack --config ../../webpack/admin.config.js --node-env development",
    "build:prod": "webpack --config ../../webpack/admin.config.js --node-env production",
    "start": "ts-node index.ts"
  },
  "dependencies": {
    "@adminjs/express": "^5.1.0",
    "@adminjs/passwords": "^3.0.1",
    "@adminjs/sequelize": "^3.0.0",
    "adminjs": "^6.8.3",
    "stream-http": "^3.2.0",
    "express-formidable": "^1.2.0",
    "express-session": "^1.17.3",
    "pg": "^8.9.0"
  },
  "devDependencies": {
    "node-loader": "^2.0.0"
  }
}


код webpack файла admin.config.js:
const path = require("path");
const DefinePlugin = require("webpack/lib/DefinePlugin");
const CopyPlugin = require("copy-webpack-plugin");
const variables = require("./variables");
const nodeExternals = require('webpack-node-externals');

module.exports = {
    entry: {
        app: "./index.ts",
    },

    target: 'node',
    externals: [
      nodeExternals(),

      // https://github.com/webpack/webpack/issues/4879
      // our engine: "pg",
      "mysql",
      "pg-hstore",
      "pg-native",
      "tedious",
      "sqlite3",

      // does not exist for linux
      "fsevents",
    ],
    externalsPresets: {
        node: true
    },

    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: "ts-loader",
                exclude: /node_modules/,
            },
            {
                test: /.node$/,
                loader: 'node-loader',
            }
        ],
    },

    resolve: {
        extensions: [".ts", ".tsx", ".js"],
        fallback: {
            "stream": require.resolve("stream-browserify"),
            "http": require.resolve("stream-http"),
        },
        modules: [
            'node_modules',
            path.resolve(__dirname, '..', '..', 'node_modules')
        ],
    },

    output: {
        filename: "admin.bundle.js",
        path: path.resolve(__dirname, "admin"),
    },

    mode: process.env.NODE_ENV,

    devtool: "source-map",

    devServer: {
        static: path.resolve(__dirname, "admin"),
        devMiddleware: {
            writeToDisk: false,
        },
        open: false,
        hot: false,
        liveReload: true,
    },

    plugins: [
        new CopyPlugin({
            patterns: [
                {
                    from: "table.sql",
                    to: "table.sql",
                    context: "../../node_modules/connect-pg-simple/",
                },
            ],
        }),
        new DefinePlugin({
            "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
            "process.env.VERSION": JSON.stringify(variables.version),
        }),
    ],

    optimization: {
        minimize: false,
    },
};


после запуска команды сборки из корня получаю следующее. В папке webpack/admin появляются 3 файла: admin.bundle.js, admin.bundle.map.js и table.sql

Перекидывая их в докер так же командой из корня через docker-compose -> dockerfile
FROM node:fermium-alpine3.16

RUN mkdir -p /app
WORKDIR /app/

COPY webpack/admin/ ./

EXPOSE 4002
CMD node ./admin.bundle.js


Получаю ошибку:
2023-02-21 11:38:53 internal/fs/utils.js:332
2023-02-21 11:38:53     throw err;
2023-02-21 11:38:53     ^
2023-02-21 11:38:53 
2023-02-21 11:38:53 Error: ENOENT: no such file or directory, open '/package.json'
2023-02-21 11:38:53     at Object.openSync (fs.js:498:3)
2023-02-21 11:38:53     at Object.readFileSync (fs.js:394:35)
2023-02-21 11:38:53     at Object.../../node_modules/adminjs/lib/adminjs.js (/app/admin.bundle.js:100249:27)
2023-02-21 11:38:53     at __webpack_require__ (/app/admin.bundle.js:549760:42)
2023-02-21 11:38:53     at Object.../../node_modules/adminjs/lib/index.js (/app/admin.bundle.js:121155:39)
2023-02-21 11:38:53     at __webpack_require__ (/app/admin.bundle.js:549760:42)
2023-02-21 11:38:53     at Object.../../node_modules/adminjs/index.js (/app/admin.bundle.js:100168:23)
2023-02-21 11:38:53     at __webpack_require__ (/app/admin.bundle.js:549760:42)
2023-02-21 11:38:53     at Object../index.ts (/app/admin.bundle.js:375885:35)
2023-02-21 11:38:53     at __webpack_require__ (/app/admin.bundle.js:549760:42) {
2023-02-21 11:38:53   errno: -2,
2023-02-21 11:38:53   syscall: 'open',
2023-02-21 11:38:53   code: 'ENOENT',
2023-02-21 11:38:53   path: '/package.json'
2023-02-21 11:38:53 }


Если в докерфайл добавить package.json строчкой в докерфайл: COPY src/admin/package.json ../package.json
FROM node:fermium-alpine3.16

RUN mkdir -p /app
WORKDIR /app/

COPY webpack/admin/ ./
+ COPY src/admin/package.json ../package.json

EXPOSE 4002
CMD node ./admin.bundle.js


То после запуска контейнера получаю уже следующую ошибку:
2023-02-21 11:46:10 internal/modules/cjs/loader.js:934
2023-02-21 11:46:10   throw err;
2023-02-21 11:46:10   ^
2023-02-21 11:46:10 
2023-02-21 11:46:10 Error: Cannot find module 'path-to-regexp'
2023-02-21 11:46:10 Require stack:
2023-02-21 11:46:10 - /app/admin.bundle.js
2023-02-21 11:46:10     at Function.Module._resolveFilename (internal/modules/cjs/loader.js:931:15)
2023-02-21 11:46:10     at Function.Module._load (internal/modules/cjs/loader.js:774:27)
2023-02-21 11:46:10     at Module.require (internal/modules/cjs/loader.js:1003:19)
2023-02-21 11:46:10     at require (internal/modules/cjs/helpers.js:107:18)
2023-02-21 11:46:10     at Object.path-to-regexp (/app/admin.bundle.js:397450:18)
2023-02-21 11:46:10     at __webpack_require__ (/app/admin.bundle.js:549760:42)
2023-02-21 11:46:10     at Object.../../node_modules/express/lib/router/layer.js (/app/admin.bundle.js:156748:18)
2023-02-21 11:46:10     at __webpack_require__ (/app/admin.bundle.js:549760:42)
2023-02-21 11:46:10     at Object.../../node_modules/express/lib/router/route.js (/app/admin.bundle.js:156942:13)
2023-02-21 11:46:10     at __webpack_require__ (/app/admin.bundle.js:549760:42) {
2023-02-21 11:46:10   code: 'MODULE_NOT_FOUND',
2023-02-21 11:46:10   requireStack: [ '/app/admin.bundle.js' ]
2023-02-21 11:46:10 }


Если запустить этот код через скрипт start то все работает как положено. Проблема именно в сборке adminjs и в чем проблема не совсем понятно. Есть может знающие?
  • Вопрос задан
  • 155 просмотров
Решения вопроса 1
McFree
@McFree Автор вопроса
JS, TS, C#
Все оказалось интереснее чем я думал.

для того чтобы запустить сборку нормально нужно было собрать бандл админки используя пакет @adminjs/bundler

после этого закидывать эти бандлы в папку assets уже для конечного webpack билда.
далее указать в adminOptions как CDN базовый путь до админки
assetsCDN: "localhost:4002"

и далее как статику указать в express папку assets
app.use(express.static("/assets"));

После чего в конфиге webpaсk для модулей были прописаны правила дополнительные, так же к CopyPlugin были добавлены 2 паттерна. Первый грузит в webpack папку assets, второй бандлы из @adminjs/design-system

Вот финальный вариант конфига для админки получился:
const path = require("path");
const DefinePlugin = require("webpack/lib/DefinePlugin");
const CopyPlugin = require("copy-webpack-plugin");
const variables = require("./variables");
const nodeExternals = require('webpack-node-externals');

module.exports = {
    entry: {
        app: "./index.ts",
    },

    target: 'node',
    externals: [
      nodeExternals(),

      // https://github.com/webpack/webpack/issues/4879
      // our engine: "pg",
      "mysql",
      "pg-hstore",
      "pg-native",
      "tedious",
      "sqlite3",

      // does not exist for linux
      "fsevents",
    ],
    externalsPresets: {
        node: true
    },

    module: {
        rules: [
            {
                test: /\.tsx?$/,
                use: "ts-loader",
                exclude: /node_modules/,
            },
            {
                test: /.node$/,
                loader: 'node-loader',
            },
            {
                test: /backend[/\\]utils[/\\]router[/\\]router\.js/,
                loader: "string-replace-loader",
                options: {
                    search: /require\.resolve\(['"]@adminjs\/design-system['"]\)/g,
                    replace: "'./assets/'",
                },
            },
            {
                test: /adminjs\.js/,
                loader: "string-replace-loader",
                options: {
                    search: /const pkg = .*?\)\)/g,
                    replace: "const pkg = {version:'6.8.3'}",
                },
            },
        ],
    },

    resolve: {
        extensions: [".ts", ".tsx", ".js"],
        fallback: {
            "stream": require.resolve("stream-browserify"),
            "http": require.resolve("stream-http"),
        },
    },

    output: {
        filename: "admin.bundle.js",
        path: path.resolve(__dirname, "admin"),
    },

    mode: process.env.NODE_ENV,

    devtool: "source-map",

    devServer: {
        static: path.resolve(__dirname, "admin"),
        devMiddleware: {
            writeToDisk: false,
        },
        open: false,
        hot: false,
        liveReload: true,
    },

    plugins: [
        new CopyPlugin({
            patterns: [
                {
                    from: "table.sql",
                    to: "table.sql",
                    context: "../../node_modules/connect-pg-simple/",
                },
                {
                    from: "assets",
                    to: "assets",
                },
                {
                    from: "bundle.*.js",
                    to: "[name].js",
                    context: "../../node_modules/@adminjs/design-system",
                }
            ],
        }),
        new DefinePlugin({
            "process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV),
            "process.env.VERSION": JSON.stringify(variables.version),
        }),
    ],

    optimization: {
        minimize: false,
    },
};
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы