diff --git a/.changeset/neat-trees-roll.md b/.changeset/neat-trees-roll.md new file mode 100644 index 00000000..12a60926 --- /dev/null +++ b/.changeset/neat-trees-roll.md @@ -0,0 +1,6 @@ +--- +"10up-toolkit": patch +"tenup-theme": patch +--- + +Feature: allow defining module script entrypoints via `moduleEntry` key in `package.json` decoupled from blocks diff --git a/packages/toolkit/__tests__/build-project-modules/.gitignore b/packages/toolkit/__tests__/build-project-modules/.gitignore new file mode 100644 index 00000000..0fa2fd4f --- /dev/null +++ b/packages/toolkit/__tests__/build-project-modules/.gitignore @@ -0,0 +1 @@ +./dist diff --git a/packages/toolkit/__tests__/build-project-modules/__fixtures__/assets/css/admin-styles.css b/packages/toolkit/__tests__/build-project-modules/__fixtures__/assets/css/admin-styles.css new file mode 100644 index 00000000..46b115dc --- /dev/null +++ b/packages/toolkit/__tests__/build-project-modules/__fixtures__/assets/css/admin-styles.css @@ -0,0 +1 @@ +.admin-class { color: blue; } diff --git a/packages/toolkit/__tests__/build-project-modules/__fixtures__/assets/css/frontend.css b/packages/toolkit/__tests__/build-project-modules/__fixtures__/assets/css/frontend.css new file mode 100644 index 00000000..635ea838 --- /dev/null +++ b/packages/toolkit/__tests__/build-project-modules/__fixtures__/assets/css/frontend.css @@ -0,0 +1 @@ +.test { color: red; } diff --git a/packages/toolkit/__tests__/build-project-modules/__fixtures__/assets/js/admin.js b/packages/toolkit/__tests__/build-project-modules/__fixtures__/assets/js/admin.js new file mode 100644 index 00000000..015d49eb --- /dev/null +++ b/packages/toolkit/__tests__/build-project-modules/__fixtures__/assets/js/admin.js @@ -0,0 +1,3 @@ +import '../css/admin-styles.css'; + +export const admin = () => {}; diff --git a/packages/toolkit/__tests__/build-project-modules/package.json b/packages/toolkit/__tests__/build-project-modules/package.json new file mode 100644 index 00000000..93a232e1 --- /dev/null +++ b/packages/toolkit/__tests__/build-project-modules/package.json @@ -0,0 +1,12 @@ +{ + "name": "test-build-project", + "10up-toolkit": { + "useBlockAssets": false, + "entry": { + "frontend-css": "./__fixtures__/assets/css/frontend.css" + }, + "moduleEntry": { + "admin": "./__fixtures__/assets/js/admin.js" + } + } +} diff --git a/packages/toolkit/__tests__/build-project-modules/test.js b/packages/toolkit/__tests__/build-project-modules/test.js new file mode 100644 index 00000000..88d188c8 --- /dev/null +++ b/packages/toolkit/__tests__/build-project-modules/test.js @@ -0,0 +1,35 @@ +/* eslint-disable import/no-extraneous-dependencies */ +import spawn from 'cross-spawn'; +import fs from 'fs'; +import path from 'path'; + +describe('build a project with moduleEntry', () => { + it('builds and compiles js and css', async () => { + spawn.sync('node', ['../../scripts/build', '--block-modules'], { + cwd: __dirname, + }); + + const adminJsPath = path.join(__dirname, 'dist', 'js', 'admin.js'); + + expect(fs.existsSync(adminJsPath)).toBeTruthy(); + expect(fs.existsSync(path.join(__dirname, 'dist', 'css', 'frontend-css.css'))).toBeTruthy(); + expect( + fs.existsSync(path.join(__dirname, 'dist', 'css', 'frontend-css.asset.php')), + ).toBeTruthy(); + + // ensure admin is a module + const adminJs = fs.readFileSync(adminJsPath).toString(); + expect(adminJs).toMatch(/export {.*};/); + }); + + it('extracts css imported in js files', () => { + spawn.sync('node', ['../../scripts/build', '--block-modules'], { + cwd: __dirname, + }); + // chunk name for css imported in js matches the js entry point + expect(fs.existsSync(path.join(__dirname, 'dist', 'css', 'admin.css'))).toBeTruthy(); + + // this should not exist since it is not an entry point on its own + expect(fs.existsSync(path.join(__dirname, 'dist', 'css', 'admin-styles.css'))).toBeFalsy(); + }); +}); diff --git a/packages/toolkit/config/__tests__/__snapshots__/webpack-cli-arguments.js.snap b/packages/toolkit/config/__tests__/__snapshots__/webpack-cli-arguments.js.snap index b1260312..f74a52f9 100644 --- a/packages/toolkit/config/__tests__/__snapshots__/webpack-cli-arguments.js.snap +++ b/packages/toolkit/config/__tests__/__snapshots__/webpack-cli-arguments.js.snap @@ -1208,7 +1208,10 @@ exports[`webpack.config.js builds modules 1`] = ` "output": { "chunkFormat": "module", "clean": false, - "filename": "blocks/[name].js", + "filename": "pathData => { + const isBlockAsset = moduleBuildFiles[pathData.chunk.name].match(/\\/blocks?\\//) || moduleBuildFiles[pathData.chunk.name].match(/\\\\blocks?\\\\/); + return isBlockAsset ? projectConfig.filenames.block : projectConfig.filenames.js; + }", "library": { "type": "module", }, diff --git a/packages/toolkit/config/webpack.config.js b/packages/toolkit/config/webpack.config.js index 7137a2e5..8b52d948 100644 --- a/packages/toolkit/config/webpack.config.js +++ b/packages/toolkit/config/webpack.config.js @@ -6,6 +6,7 @@ const { getTenUpScriptsConfig, getTenUpScriptsPackageBuildConfig, } = require('../utils'); +const { getModuleBuildFiles } = require('../utils/config'); const { getEntryPoints, @@ -25,6 +26,7 @@ const projectConfig = getTenUpScriptsConfig(); const packageConfig = getTenUpScriptsPackageBuildConfig(); const { source, main } = packageConfig; const buildFiles = getBuildFiles(); +const moduleBuildFiles = getModuleBuildFiles(); // assume it's a package if there's source and main const isPackage = typeof source !== 'undefined' && typeof main !== 'undefined'; @@ -44,6 +46,7 @@ const config = { projectConfig, packageConfig, buildFiles, + moduleBuildFiles, isPackage, mode, isProduction, @@ -95,7 +98,12 @@ const moduleConfig = { ...baseConfig.output.library, type: 'module', }, - filename: 'blocks/[name].js', + filename: (pathData) => { + const isBlockAsset = + moduleBuildFiles[pathData.chunk.name].match(/\/blocks?\//) || + moduleBuildFiles[pathData.chunk.name].match(/\\blocks?\\/); + return isBlockAsset ? projectConfig.filenames.block : projectConfig.filenames.js; + }, }, }; diff --git a/packages/toolkit/config/webpack/entry.js b/packages/toolkit/config/webpack/entry.js index 5f66b3af..f08458f6 100644 --- a/packages/toolkit/config/webpack/entry.js +++ b/packages/toolkit/config/webpack/entry.js @@ -12,6 +12,7 @@ module.exports = ({ projectConfig: { devServer, paths, useBlockAssets, filenames }, packageConfig: { packageType, source, main, umd, libraryName }, buildFiles, + moduleBuildFiles, }) => { let additionalEntrypoints = {}; if (useBlockAssets) { @@ -105,7 +106,8 @@ module.exports = ({ } if (buildType === 'module') { - return additionalEntrypoints; + Object.assign(moduleBuildFiles, additionalEntrypoints); + return moduleBuildFiles; } // merge the new entrypoints with the existing ones diff --git a/packages/toolkit/utils/config.js b/packages/toolkit/utils/config.js index ca8554ad..c9b72637 100644 --- a/packages/toolkit/utils/config.js +++ b/packages/toolkit/utils/config.js @@ -124,6 +124,7 @@ const getDefaultConfig = () => { return { entry: require(buildFilesPath), + moduleEntry: {}, filenames: require(filenamesPath), paths: require(pathsPath), wordpress: wpMode !== 'false', @@ -295,6 +296,22 @@ const getBuildFiles = () => { return entries; }; +const getModuleBuildFiles = () => { + const { moduleEntry } = getTenUpScriptsConfig(); + + const entries = {}; + + Object.keys(moduleEntry).forEach((key) => { + const filePath = path.resolve(process.cwd(), moduleEntry[key]); + + if (fileExists(filePath)) { + entries[key] = filePath; + } + }); + + return entries; +}; + module.exports = { hasBabelConfig, getJestOverrideConfigFile, @@ -303,6 +320,7 @@ module.exports = { hasPostCSSConfig, hasStylelintConfig, getBuildFiles, + getModuleBuildFiles, hasEslintignoreConfig, hasEslintConfig, getTenUpScriptsConfig, diff --git a/projects/10up-theme/assets/js/frontend/frontend-module.js b/projects/10up-theme/assets/js/frontend/frontend-module.js new file mode 100644 index 00000000..c606cecc --- /dev/null +++ b/projects/10up-theme/assets/js/frontend/frontend-module.js @@ -0,0 +1,12 @@ +import { store } from '@wordpress/interactivity'; + +const { state } = store('frontend', { + state: { + isExpanded: false, + }, + actions: { + toggleExpanded() { + state.isExpanded = !state.isExpanded; + }, + }, +}); diff --git a/projects/10up-theme/package.json b/projects/10up-theme/package.json index 22513459..8e9cc981 100644 --- a/projects/10up-theme/package.json +++ b/projects/10up-theme/package.json @@ -46,6 +46,9 @@ "styleguide-style": "./assets/css/styleguide/styleguide.css", "core-block-overrides": "./includes/core-block-overrides.js", "test-style": "./assets/css/frontend/testing.scss" - } + }, + "moduleEntry": { + "frontend-module": "./assets/js/frontend/frontend-module.js" + } } }