Ctrl K
ComunidadGuías…

webpack.config.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
/*
 * Silex website builder, free/libre no-code tool for makers.
 * Copyright (c) 2023 lexoyo and Silex Labs foundation
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

const fs = require('fs')
const path = require('path');
const webpack = require("webpack")
const HtmlWebpackPlugin = require('html-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

// Monorepo: compile the grapesjs-* plugins from their SOURCE in a single pass,
// instead of pulling each plugin's pre-built dist/. This removes the per-plugin
// build step (the plugins are now plain source folders in the monorepo).
// `$` = exact match, so subpath imports (e.g. .../src/commands) still resolve normally.
const pluginSrc = {
  '@silexlabs/grapesjs-filter-styles$': './grapesjs-plugins/grapesjs-filter-styles/src/index.js',
  '@silexlabs/grapesjs-symbols$': './grapesjs-plugins/grapesjs-symbols/src/index.ts',
  '@silexlabs/grapesjs-loading$': './grapesjs-plugins/grapesjs-loading/src/index.ts',
  '@silexlabs/grapesjs-fonts$': './grapesjs-plugins/grapesjs-fonts/src/index.js',
  '@silexlabs/grapesjs-css-variables$': './grapesjs-plugins/grapesjs-css-variables/src/index.js',
  '@silexlabs/grapesjs-advanced-selector$': './grapesjs-plugins/grapesjs-advanced-selector/src/index.ts',
  '@silexlabs/grapesjs-storage-rate-limit$': './grapesjs-plugins/grapesjs-storage-rate-limit/src/index.js',
  '@silexlabs/grapesjs-notifications$': './grapesjs-plugins/grapesjs-notifications/src/index.ts',
  '@silexlabs/grapesjs-keymaps-dialog$': './grapesjs-plugins/grapesjs-keymaps-dialog/src/index.ts',
  '@silexlabs/grapesjs-ai-capabilities$': './grapesjs-plugins/grapesjs-ai-capabilities/src/index.js',
  '@silexlabs/grapesjs-data-source$': './grapesjs-plugins/grapesjs-data-source/src/index.ts',
  '@silexlabs/expression-input$': './grapesjs-plugins/expression-input/src/index.ts',
}
// Monorepo path aliases (mirror tsconfig "paths"): cross-area imports use ~/ aliases
// instead of brittle ../../ relatives. editor (client) is bundled by webpack, which
// resolves these directly; the server (tsc) gets them rewritten to relative by tsc-alias.
const areaAliases = {
  '~/common': path.resolve(__dirname, 'common'),
  '~/editor': path.resolve(__dirname, 'editor'),
  '~/server': path.resolve(__dirname, 'server'),
  '~/grapesjs-plugins': path.resolve(__dirname, 'grapesjs-plugins'),
}
const pluginAliases = {
  ...Object.fromEntries(
    Object.entries(pluginSrc).map(([k, v]) => [k, path.resolve(__dirname, v)])
  ),
  ...areaAliases,
}

module.exports = {
  entry: './editor/index.ts',
  mode: 'production',
  module: {
    rules: [
      {
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          { loader: 'css-loader', options: { url: false } },
          {
            loader: 'sass-loader',
            options: { sassOptions: { loadPaths: ['node_modules'], quietDeps: true } },
          },
        ],
      },
      {
        test: /\.tsx?$/,
        loader: 'ts-loader',
        // Bundling only: type-checking is a separate CI job (tsc/lint).
        // Required to transpile the plugin sources (compiled here, not pre-built).
        // experimentalDecorators + useDefineForClassFields:false: the lit-based
        // plugins (data-source, advanced-selector, expression-input) use legacy
        // decorators (@property/@state); ESNext target would otherwise break them.
        options: {
          transpileOnly: true,
          compilerOptions: {
            experimentalDecorators: true,
            emitDecoratorMetadata: true,
            useDefineForClassFields: false,
          },
        },
      },
    ]
  },
  resolve: {
  extensions: ['.tsx', '.ts', '.js'],
  // TS ESM sources (e.g. expression-input) import siblings as "./x.js" while the
  // file is "x.ts"; let webpack resolve a ".js" specifier to its ".ts" source.
  extensionAlias: { '.js': ['.ts', '.js'], '.mjs': ['.mts', '.mjs'] },
  alias: pluginAliases,
  modules: [
    path.resolve(__dirname, 'node_modules'),
  ],
},

  output: {
    filename: 'js/[name].[contenthash:8].js',
    path: path.resolve(__dirname, 'dist/client'),
    library: 'silex',
    // The watch reruns this build alone: the files of build:public would not come back
    clean: { keep: (file) => !/^js\/|^css\/admin\./.test(file) },
  },
  plugins: [
    new webpack.DefinePlugin({
      SILEX_VERSION_ENV: JSON.stringify(require("./package.json").version),
    }),
    new webpack.IgnorePlugin({
      resourceRegExp: /^jquery$/,
      contextRegExp: /backbone/
    }),
    new MiniCssExtractPlugin({
      filename: 'css/admin.[contenthash:8].css',
    }),
    new HtmlWebpackPlugin({
      template: './editor/index.ejs',
      filename: 'index.html',
      inject: false,
      // Inlined: the page is painted before the stylesheet arrives
      templateParameters: { tokens: fs.readFileSync(path.resolve(__dirname, 'editor/css/tokens.css'), 'utf8') },
    }),
    // The dashboard of the hosted Silex (silex-dashboard submodule) loads the editor at /js/main.js:
    // also emit the bundle under its stable name
    {
      apply(compiler) {
        compiler.hooks.thisCompilation.tap('StableMainAlias', (compilation) => {
          compilation.hooks.processAssets.tap(
            { name: 'StableMainAlias', stage: compiler.webpack.Compilation.PROCESS_ASSETS_STAGE_REPORT },
            (assets) => {
              const hashed = Object.keys(assets).find((name) => /^js\/main\..*\.js$/.test(name))
              if (hashed) compilation.emitAsset('js/main.js', assets[hashed])
            }
          )
        })
      },
    },
  ]
};