Skip to content

Build the backend assets with webpack instead of gulp - #461

Merged
daphneslootmans merged 5 commits into
masterfrom
chore/webpack-backend-build
Nov 2, 2026
Merged

daphneslootmans merged 5 commits into
masterfrom
chore/webpack-backend-build

Conversation

@daphneslootmans

@daphneslootmans daphneslootmans commented Oct 30, 2026 •

Copy link
Copy Markdown

Type

  • Enhancement

Resolves the following issues

The backend assets still built through a legacy gulpfile.js (Gulp 4 and 6 gulp plugins), next to the webpack build for the theme. Two build tools, and CI ran both.

Pull request description

Audit of the gulp tasks

All gulp output is committed to git, so dropping a task leaves the last built file in place.

Gulp task Result Reason
backend vendor CSS, JS, fonts, fine-uploader ported all referenced by the backend (Header.php, MediaLibrary, Pages, DatePickerType)
backend CKEditor copy ported, simplified codemirror and lineutils are not in the npm package (committed custom copies), duplicate iframe line removed
backend Sass (screen.scss, debug.scss) ported
serve:* + livereload removed npm run watch covers it
frontend core, Search, Fork theme, photoswipe, bootstrap.bundle.js, slick.min.js dropped Fork theme is not active (installer sets Custom), frontend core screen.css is Bootstrap 3 on BS5 themes, photoswipe was replaced by fslightbox, bootstrap.bundle and slick are unreferenced

Changes

  • New webpack.backend.js, exported next to the theme config from webpack.dev.js and webpack.prod.js.
  • gulpfile.js and the gulp packages removed, webpack-remove-empty-scripts added.
  • CI (GitLab and GitHub) runs npm run build only.
  • Theme config: modern Sass API, deprecation warnings from node_modules silenced, no more empty screen.js / editor_content.js.

Things that needed care

  • css-loader runs with url: false: the backend Sass uses absolute /src/... and /fonts/vendors URLs.
  • Copied vendor files skip the minimizer (info.minimized), otherwise production mode re-minifies them.
  • The npm ckeditor JS ships with a UTF-8 BOM that gulp stripped. A copy transform strips it too, so the 655 committed files stay unchanged.

Verification

  • npm run build: vendor copies and CKEditor byte-identical to git, backend screen.css has the same 2554 rules (whitespace-only diff), theme output byte-identical apart from the removed empty stubs.
  • npm run watch rebuilds backend CSS on change.
  • Tested in a project: backend login, dashboard, CKEditor, MediaLibrary upload + cropper, datepicker, tags input.

Follow-ups (not in this PR)

  • Stop loading Bootstrap 3 Frontend/Core/Layout/Css/screen.css in Frontend/Core/Header/Header.php.
  • Stop loading photoswipe in Frontend/Modules/MediaLibrary/Widgets/Lightbox.php for BS5 themes.
  • Decide on the Fork theme, the orphaned frontend Sass sources and the leftover bootstrap@4, photoswipe, slick-carousel packages.

🤖 Generated with Claude Code

Summary by Sourcery

Consolidate theme and backend asset generation into a single webpack-based build and retire the legacy Gulp pipeline.

New Features:

  • Build backend styles and vendor assets through webpack alongside the existing theme assets.

Enhancements:

  • Replace the legacy Gulp asset pipeline with a unified webpack build and remove obsolete frontend asset outputs.
  • Preserve required backend vendor and CKEditor assets while eliminating empty generated JavaScript stubs.
  • Update development watching and asset deployment to include backend webpack outputs.

Build:

  • Remove Gulp dependencies and configuration, and add webpack support for backend asset compilation and copying.

CI:

  • Update GitHub and GitLab CI to run the unified npm build only.

Deployment:

  • Update deployment configuration and build commands for the webpack-only asset pipeline.

Documentation:

  • Update asset build instructions to document the unified webpack build.

Chores:

  • Refresh generated backend CSS and dependency lockfile contents after removing the legacy build tooling.

Daphne Slootmans and others added 2 commits October 30, 2026 15:52
Move the backend Sass build and the vendor copies (jQuery, Bootstrap 3 JS,
datepicker, tagsinput, cropper, fine-uploader, Font Awesome 4 fonts and
CKEditor) from gulpfile.js into webpack.backend.js, exported next to the
theme config from webpack.dev.js and webpack.prod.js.

The frontend core, Search, Fork theme and photoswipe tasks are dropped:
nothing active builds from them and their output stays committed.

The CKEditor copy skips codemirror and lineutils (not in the npm package)
and strips the UTF-8 BOM the npm files ship with, so the committed copies
stay unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Switch the theme sass-loader to the modern Sass API and silence
  deprecation warnings coming from node_modules (bootstrap5).
- Drop the empty screen.js and editor_content.js stubs the theme build
  emitted for its Sass-only entries.
- Write the BOM in the CKEditor copy transform as an escape instead of a
  literal invisible character.
- Use StandardJS style in webpack.dev.js and webpack.prod.js.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Oct 30, 2026 •

Copy link
Copy Markdown

Reviewer's Guide

Consolidates backend and theme asset compilation under webpack by introducing a dedicated backend compiler, migrating required vendor and CKEditor outputs while preserving committed-file compatibility, removing the Gulp toolchain and obsolete assets, and updating CI, deployment, and documentation to run the unified build.

Sequence diagram for unified asset build in CI

sequenceDiagram
    participant CI
    participant NPM as npm run build
    participant Webpack
    participant ThemeCompiler
    participant BackendCompiler
    participant Assets as Committed asset outputs

    CI->>NPM: npm run build
    NPM->>Webpack: Run webpack.prod.js
    Webpack->>ThemeCompiler: Build theme assets
    Webpack->>BackendCompiler: Build backend assets
    BackendCompiler->>Assets: Compile backend Sass
    BackendCompiler->>Assets: Copy vendor files
    BackendCompiler->>Assets: Copy CKEditor files
    ThemeCompiler->>Assets: Write theme assets
Loading

Flow diagram for backend asset migration from Gulp to Webpack

flowchart LR
    Gulp[Gulp backend pipeline]
    BackendConfig[webpack.backend.js]
    Sass[Backend Sass]
    Vendors[Vendor and CKEditor files]
    CSS[Backend CSS outputs]
    JS[Backend vendor and CKEditor outputs]

    Gulp -. removed .-> BackendConfig
    BackendConfig --> Sass
    BackendConfig --> Vendors
    Sass --> CSS
    Vendors --> JS
Loading

File-Level Changes

Change Details Files
Replace the legacy Gulp backend asset pipeline with a dedicated webpack compiler.
  • Add backend Sass entries for screen and debug styles.
  • Copy required vendor assets and CKEditor files into their existing committed locations.
  • Preserve committed outputs by disabling cleanup, avoiding minimization of copied files, and stripping CKEditor BOMs.
  • Remove obsolete frontend and live-reload Gulp tasks.
webpack.backend.js
gulpfile.js
package.json
package-lock.json
src/Backend/Core/Layout/Css/debug.css
src/Backend/Core/Layout/Css/debug.css.map
src/Backend/Core/Layout/Css/screen.css
src/Backend/Core/Layout/Css/screen.css.map
Run backend and theme builds through a unified webpack invocation in development and production.
  • Export theme and backend configurations as multi-compiler webpack configs.
  • Remove empty JavaScript stubs from CSS-only entries.
  • Modernize Sass loader configuration and preserve absolute asset URLs.
  • Watch backend CSS outputs for browser reloads.
webpack.common.js
webpack.dev.js
webpack.prod.js
package.json
Update automation, deployment, and documentation to use the consolidated build.
  • Change GitHub Actions and GitLab CI to run only npm run build.
  • Update deployment packaging and local build commands for webpack.backend.js.
  • Document the unified theme and backend asset build.
.github/workflows/ci.yml
.gitlab-ci.yml
deploy.php
CLAUDE.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 6 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="package.json" line_range="35" />
<code_context>
         "css-loader": "^6.8.1",
         "fine-uploader": "^5.14.1",
         "font-awesome": "^4.7.0",
-        "gulp": "^4.0.2",
-        "gulp-autoprefixer": "^8.0.0",
-        "gulp-livereload": "^4.0.1",
</code_context>
<issue_to_address>
**Deployment asset builds stop**

When a deployment reaches `fork:theme:build` with dependencies installed from the new lockfile, `fork:theme:build` runs `node_modules/.bin/gulp build` before `npm run build`, but Gulp was removed from the dependencies and the gulpfile was deleted, so the command exits nonzero and the webpack build and asset upload do not run.

Update `fork:theme:build` to run the asset build without Gulp, or restore the Gulp dependency and gulpfile.
</issue_to_address>

### Comment 2
<location path="webpack.backend.js" line_range="1" />
<code_context>
+const path = require('path')
+const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const RemoveEmptyScriptsPlugin = require('webpack-remove-empty-scripts')
</code_context>
<issue_to_address>
**Backend build config is exposed**

When a deployment uses the `clear_paths` list and serves the release through the repository’s `.htaccess` rules, `deploy.php` does not remove `webpack.backend.js` as it does the other webpack configs, and `.htaccess` does not block it; Apache serves the deployed file directly, exposing the backend asset build configuration to visitors.

Add `webpack.backend.js` to `deploy.php`’s `clear_paths` and explicitly block it in `.htaccess` for deployments that do not use that list.
</issue_to_address>

### Comment 3
<location path="webpack.backend.js" line_range="90-100" />
<code_context>
+          'font-awesome/fonts/*'
+        ], 'fonts/vendors'),
+        ...copyVendorFiles([
+          'jquery/dist/jquery.min.js',
+          'jquery-migrate/dist/jquery-migrate.min.js',
+          'jquery-ui-dist/jquery-ui.min.js',
+          'bootstrap-sass/assets/javascripts/bootstrap.min.js',
+          'bootstrap-tagsinput/dist/bootstrap-tagsinput.min.js',
+          'fine-uploader/jquery.fine-uploader/jquery.fine-uploader.min.js',
+          'simple-ajax-uploader/SimpleAjaxUploader.min.js',
+          'bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js',
+          'cropper/dist/cropper.js',
+          'bootstrap-accessibility-plugin/plugins/js/bootstrap-accessibility.min.js'
+        ], 'js/vendors'),
+        ...ckeditorFiles.map((file) => ({
+          from: file,
</code_context>
<issue_to_address>
**Autocomplete scripts are missing**

When the committed typeahead asset is absent or removed, or the unified webpack build is used to produce assets, the vendor copy list omits `typeahead.bundle.min.js` while `Header::addCoreJs()` and frontend Search still request it, so backend typeahead widgets and frontend autocomplete load a missing script and stop working.

Add `typeahead.bundle.min.js` to the webpack vendor copy list.
</issue_to_address>

### Comment 4
<location path="webpack.backend.js" line_range="9" />
<code_context>
+// copies node_modules files flat into a folder in the project root, untouched by the minimizer
+const copyVendorFiles = (files, folder) => files.map((file) => ({
+  from: `node_modules/${file}`,
+  to: path.resolve(__dirname, folder, '[name][ext]'),
+  info: { minimized: true }
+}))
</code_context>
<issue_to_address>
**Vendor assets go to wrong directories**

When `npm run build` copies vendor assets, `copyVendorFiles` resolves `css/vendors` and `js/vendors` from the repository root, while `Header::buildPathForModule()` serves Core assets from `src/Backend/Core/...`; webpack therefore writes vendor copies to unserved directories and leaves the served copies stale.

Resolve each vendor destination under its corresponding `src/Backend/Core` asset directory instead of the repository root.
</issue_to_address>

### Comment 5
<location path="webpack.dev.js" line_range="10-12" />
<code_context>
+    mode: 'development',
+    devtool: 'inline-source-map'
+  }),
+  merge(backend, {
+    mode: 'development'
+  })
+]
</code_context>
<issue_to_address>
**Backend Sass edits do not reload**

When a backend Sass file changes while `npm run watch` is running, the backend webpack compiler rebuilds its CSS without running the `BrowserSyncPlugin` hook, which is only registered in `webpack.common.js` for the separate theme compiler. The page stays stale until manually refreshed.

Configure BrowserSync to reload on backend compiler completion or watch the backend CSS output for changes.
</issue_to_address>

### Comment 6
<location path=".github/workflows/ci.yml" line_range="80" />
<code_context>
-                run: |
-                    node_modules/.bin/gulp build
-                    npm run build
+                run: npm run build


</code_context>
<issue_to_address>
**CI no longer runs Gulp**

Both CI jobs now run `npm run build`, which invokes webpack; neither runs Gulp, so the recorded CI build fact is false.

Update the knowledge-base entry to reflect that CI now builds assets with webpack only.

Also at `.gitlab-ci.yml:53`.
</issue_to_address>

Sourcery assessment

Approval pending. 3 findings to address first.

Blocking findings: package.json:35, webpack.backend.js:100, webpack.backend.js:9


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread package.json Resolved
Comment thread webpack.backend.js
@@ -0,0 +1,144 @@
const path = require('path')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚪ Low · Backend build config is exposed

When a deployment uses the clear_paths list and serves the release through the repository’s .htaccess rules, deploy.php does not remove webpack.backend.js as it does the other webpack configs, and .htaccess does not block it; Apache serves the deployed file directly, exposing the backend asset build configuration to visitors.

Add webpack.backend.js to deploy.php’s clear_paths and explicitly block it in .htaccess for deployments that do not use that list.

Prompt for AI agents
In `webpack.backend.js` at line 1:

**Backend build config is exposed**

When a deployment uses the `clear_paths` list and serves the release through the repository’s `.htaccess` rules, `deploy.php` does not remove `webpack.backend.js` as it does the other webpack configs, and `.htaccess` does not block it; Apache serves the deployed file directly, exposing the backend asset build configuration to visitors.

Add `webpack.backend.js` to `deploy.php`’s `clear_paths` and explicitly block it in `.htaccess` for deployments that do not use that list.

Comment thread webpack.backend.js Resolved
Comment thread webpack.backend.js Resolved
Comment thread webpack.dev.js Resolved
Comment thread .github/workflows/ci.yml Resolved
Daphne Slootmans and others added 3 commits October 30, 2026 16:42
fork:theme:build still ran node_modules/.bin/gulp build before
npm run build. Gulp is gone, so every deploy failed at that step.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clear webpack.backend.js on deploy like the other webpack configs and
block all webpack.*.js files in .htaccess. Drop the gulpfile.js entries,
that file no longer exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The backend builds in its own webpack compiler, so BrowserSync only
reloaded on theme changes. Watch the backend CSS output as well, like
gulp serve did with livereload.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@daphneslootmans

Copy link
Copy Markdown
Author

@sourcery-ai review

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path=".github/workflows/ci.yml" line_range="80" />
<code_context>
-                run: |
-                    node_modules/.bin/gulp build
-                    npm run build
+                run: npm run build


</code_context>
<issue_to_address>
**CI no longer runs Gulp**

When the GitHub or GitLab asset-build job runs, both jobs now run only `npm run build`, so the knowledge-base fact that CI still uses the legacy Gulp pipeline is no longer true.

Update kb-423824 to reflect that CI now builds assets with webpack only.

Also at `.gitlab-ci.yml:53`.
</issue_to_address>

Sourcery assessment

Approved.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread .github/workflows/ci.yml Resolved
@daphneslootmans
daphneslootmans merged commit 5012da4 into master Nov 2, 2026
9 of 12 checks passed
@daphneslootmans
daphneslootmans deleted the chore/webpack-backend-build branch November 2, 2026 12:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants