Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refine asset handling to better reflect modern block development #195

Merged
merged 17 commits into from
Aug 1, 2022
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7,155 changes: 949 additions & 6,206 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions packages/toolkit/config/__tests__/webpack-basic-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ describe('webpack.config.js', () => {
'10up-toolkit': {
entry: entryBuildFiles,
paths: {
blocksDir: './includes2/blocks/',
srcDir: './assets2/',
cssLoaderPaths: ['./assets2/css', './includes2/blocks'],
copyAssetsDir: './assets2/',
Expand Down Expand Up @@ -178,6 +179,7 @@ describe('webpack.config.js', () => {
'10up-toolkit': {
entry: entryBuildFiles,
paths: {
blocksDir: './includes2/blocks/',
srcDir: './assets2/',
cssLoaderPaths: ['./assets2/css', './includes2/blocks'],
copyAssetsDir: './assets2/',
Expand Down
4 changes: 2 additions & 2 deletions packages/toolkit/config/filenames.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ module.exports = {
js: 'js/[name].js',
jsChunk: 'js/[name].[contenthash].chunk.js',
css: 'css/[name].css',
block: 'blocks/[name]/editor.js',
blockCSS: 'blocks/[name]/editor.css',
block: 'blocks/[name].js',
blockCSS: 'blocks/[name].css',
};
1 change: 1 addition & 0 deletions packages/toolkit/config/paths.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ module.exports = {
srcDir: './assets/',
cssLoaderPaths: ['./assets/css', './includes/blocks'],
copyAssetsDir: './assets/',
blocksDir: './includes/blocks/',
fabiankaegy marked this conversation as resolved.
Show resolved Hide resolved
};
4 changes: 2 additions & 2 deletions packages/toolkit/config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const {
getModules,
getResolve,
getTarget,
getPerfomance,
getPerformance,
fabiankaegy marked this conversation as resolved.
Show resolved Hide resolved
getDevServer,
} = require('./webpack');

Expand Down Expand Up @@ -59,7 +59,7 @@ module.exports = {
target: getTarget(config),
resolve: getResolve(config),
externals: getExternals(config),
performance: getPerfomance(config),
performance: getPerformance(config),
fabiankaegy marked this conversation as resolved.
Show resolved Hide resolved
module: getModules(config),
plugins: getPlugins(config),
stats: getStats(config),
Expand Down
20 changes: 15 additions & 5 deletions packages/toolkit/config/webpack/__tests__/entry.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,24 @@ describe('entry module function', () => {
it('returns project mode entry config', () => {
const buildFiles = { entry: 'entry.js' };
expect(
entry({ isPackage: false, packageConfig: {}, projectConfig: {}, buildFiles }),
entry({
isPackage: false,
packageConfig: {},
projectConfig: { paths: { blocksDir: './includes2/blocks/' } },
buildFiles,
}),
).toEqual(buildFiles);
});

it('returns package mode entry config', () => {
const buildFiles = { entry: 'entry.js' };
expect(
entry({ isPackage: true, packageConfig: {}, projectConfig: {}, buildFiles }),
entry({
isPackage: true,
packageConfig: {},
projectConfig: { paths: { blocksDir: './includes2/blocks/' } },
buildFiles,
}),
).toEqual(buildFiles);

expect(
Expand All @@ -24,7 +34,7 @@ describe('entry module function', () => {
umd: 'index.umd.js',
libraryName: 'LibraryName',
},
projectConfig: {},
projectConfig: { paths: { blocksDir: './includes2/blocks/' } },
buildFiles: [],
}),
).toEqual({
Expand Down Expand Up @@ -54,7 +64,7 @@ describe('entry module function', () => {
main: 'index.js',
libraryName: 'LibraryName',
},
projectConfig: {},
projectConfig: { paths: { blocksDir: './includes2/blocks/' } },
buildFiles: [],
}),
).toEqual({
Expand All @@ -76,7 +86,7 @@ describe('entry module function', () => {
main: 'index.js',
libraryName: 'LibraryName',
},
projectConfig: {},
projectConfig: { paths: { blocksDir: './includes2/blocks/' } },
buildFiles: [],
}),
).toEqual({
Expand Down
56 changes: 55 additions & 1 deletion packages/toolkit/config/webpack/entry.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,67 @@
const { readFileSync } = require('fs');
const { dirname, extname, join, resolve } = require('path');
const { sync: glob } = require('fast-glob');

const removeDistFolder = (file) => {
return file.replace(/(^\.\/dist\/)|^dist\//, '');
};

module.exports = ({
isPackage,
projectConfig: { devServer },
projectConfig: { devServer, paths },
packageConfig: { packageType, source, main, umd, libraryName },
buildFiles,
}) => {
const blocksSourceDirectory = resolve(process.cwd(), paths.blocksDir);

// get all block.json files in the blocks directory
const blockMetadataFiles = glob(`${blocksSourceDirectory}/**/block.json`, {
absolute: true,
});

// add any additional entrypoints we find in block.json filed to the webpack config
const additionalEntrypoints = blockMetadataFiles.reduce((accumulator, blockMetadataFile) => {
// get all assets from the block.json file
const { editorScript, script, viewScript, style, editorStyle } = JSON.parse(
readFileSync(blockMetadataFile),
);

// generate a new entrypoint for each of the assets
[editorScript, script, viewScript, style, editorStyle]
.flat()
.filter((rawFilepath) => rawFilepath && rawFilepath.startsWith('file:')) // assets can be files or handles. we only want files
.forEach((rawFilepath) => {
// Removes the `file:` prefix.
const filepath = join(dirname(blockMetadataFile), rawFilepath.replace('file:', ''));

// get the entrypoint name from the filepath by removing the blocks source directory and the file extension
const entryName = filepath
.replace(extname(filepath), '')
.replace(blocksSourceDirectory, '')
.replace(/\\/g, '/');

// Detects the proper file extension used in the defined source directory.
const [entryFilepath] = glob(
`${blocksSourceDirectory}/${entryName}.([jt]s?(x)|?(s)css)`,
{
absolute: true,
},
);

if (!entryFilepath) {
// eslint-disable-next-line no-console
console.warn('There was no entry file found for', entryName);
return;
}

accumulator[entryName] = entryFilepath;
});
return accumulator;
}, {});

// merge the new entrypoints with the existing ones
Object.assign(buildFiles, additionalEntrypoints);

if (isPackage) {
const config = {};
const hasBuildFiles = Object.keys(buildFiles).length > 0;
Expand Down
4 changes: 2 additions & 2 deletions packages/toolkit/config/webpack/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const getOptimization = require('./optimization');
const getModules = require('./modules');
const getResolve = require('./resolve');
const getTarget = require('./target');
const getPerfomance = require('./perfomance');
const getPerformance = require('./performance');
fabiankaegy marked this conversation as resolved.
Show resolved Hide resolved
const getDevServer = require('./devServer');

module.exports = {
Expand All @@ -20,6 +20,6 @@ module.exports = {
getModules,
getResolve,
getTarget,
getPerfomance,
getPerformance,
fabiankaegy marked this conversation as resolved.
Show resolved Hide resolved
getDevServer,
};
2 changes: 1 addition & 1 deletion packages/toolkit/config/webpack/optimization.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module.exports = ({ isProduction, projectConfig: { hot, analyze } }) => {
terserOptions: {
parse: {
// We want terser to parse ecma 8 code. However, we don't want it
// to apply any minfication steps that turns valid ecma 5 code
// to apply any minification steps that turns valid ecma 5 code
fabiankaegy marked this conversation as resolved.
Show resolved Hide resolved
// into invalid ecma 5 code. This is why the 'compress' and 'output'
// sections only apply transformations that are ecma 5 safe
// https://github.com/facebook/create-react-app/pull/4234
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
/**
* Converts a size vlaue to bytes
* Converts a size value to bytes
fabiankaegy marked this conversation as resolved.
Show resolved Hide resolved
*
* @param {number} size The size in kb
*
* @return {number} The size in bytes
* @returns {number} The size in bytes
fabiankaegy marked this conversation as resolved.
Show resolved Hide resolved
*/
const kb = (size) => {
return size * 1024;
Expand Down
12 changes: 10 additions & 2 deletions packages/toolkit/config/webpack/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ module.exports = ({
hot,
},
packageConfig: { style },
buildFiles,
}) => {
const hasReactFastRefresh = hot && !isProduction;

Expand Down Expand Up @@ -93,7 +94,9 @@ module.exports = ({
return removeDistFolder(style);
}

return options.chunk.name.match(/-block$/) ? filenames.blockCSS : filenames.css;
return buildFiles[options.chunk.name].match(/\/blocks\//)
? filenames.blockCSS
: filenames.css;
},
chunkFilename: '[id].css',
}),
Expand All @@ -108,6 +111,11 @@ module.exports = ({
noErrorOnMissing: true,
context: path.resolve(process.cwd(), paths.copyAssetsDir),
},
{
from: '**/block.json',
context: path.resolve(process.cwd(), paths.blocksDir),
to: 'blocks/[path][name][ext]',
},
hasReactFastRefresh && {
from: fromConfigRoot('fast-refresh.php'),
to: '[path][name][ext]',
Expand All @@ -130,7 +138,7 @@ module.exports = ({
}),
// Fancy WebpackBar.
!hasReactFastRefresh && new WebpackBar(),
// dependecyExternals variable controls whether scripts' assets get
// dependencyExternals variable controls whether scripts' assets get
fabiankaegy marked this conversation as resolved.
Show resolved Hide resolved
// generated, and the default externals set.
wpDependencyExternals &&
!isPackage &&
Expand Down
4 changes: 3 additions & 1 deletion packages/toolkit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
"bin": {
"10up-toolkit": "bin/10up-toolkit.js"
},
"bundleDependencies": [],
"dependencies": {
"@babel/core": "^7.17.8",
"@babel/eslint-parser": "^7.17.0",
Expand All @@ -38,12 +37,15 @@
"css-loader": "^6.7.1",
"cssnano": "^5.1.7",
"eslint-webpack-plugin": "^3.1.1",
"fast-glob": "^3.2.11",
"fs": "^0.0.1-security",
fabiankaegy marked this conversation as resolved.
Show resolved Hide resolved
"html-webpack-plugin": "^5.5.0",
"ignore-emit-webpack-plugin": "2.0.6",
"image-minimizer-webpack-plugin": "^3.2.3",
"jest": "^27.5.1",
"mini-css-extract-plugin": "^2.6.0",
"minimist": "^1.2.6",
"path": "^0.12.7",
fabiankaegy marked this conversation as resolved.
Show resolved Hide resolved
"postcss": "^8.4.12",
"postcss-editor-styles": "^0.3.0",
"postcss-import": "^14.1.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/toolkit/test-utils/resolver.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const glob = require('glob');
const { sync: glob } = require('fast-glob');

let mapping = {};
// Looks for "module-resolution.json" files in all the `__tests__` directories
glob.sync(`${__dirname}/../**/__tests__/modules-resolution.json`).forEach((file) => {
glob(`${__dirname}/../**/__tests__/modules-resolution.json`).forEach((file) => {
// For each of them, merges them in the "mapping" object
mapping = { ...mapping, ...require(file) };
});
Expand Down
3 changes: 3 additions & 0 deletions projects/10up-theme/.wp-env.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"themes": [ "." ]
}
1 change: 1 addition & 0 deletions projects/10up-theme/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
define( 'TENUP_THEME_DIST_URL', TENUP_THEME_TEMPLATE_URL . '/dist/' );
define( 'TENUP_THEME_INC', TENUP_THEME_PATH . 'includes/' );
define( 'TENUP_THEME_BLOCK_DIR', TENUP_THEME_INC . 'blocks/' );
define( 'TENUP_THEME_BLOCK_DIST_DIR', TENUP_THEME_PATH . 'dist/blocks/' );

if ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG && file_exists( __DIR__ . '/dist/fast-refresh.php' ) ) {
require_once __DIR__ . '/dist/fast-refresh.php';
Expand Down
19 changes: 0 additions & 19 deletions projects/10up-theme/includes/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,34 +47,15 @@ function setup() {
* @return void
*/
function register_theme_blocks() {
// Filter the plugins URL to allow us to have blocks in themes with linked assets. i.e editorScripts
add_filter( 'plugins_url', __NAMESPACE__ . '\filter_plugins_url', 10, 2 );


// Require custom blocks.
require_once TENUP_THEME_BLOCK_DIR . '/example-block/register.php';

// Call block register functions for each block.
Example\register();

// Remove the filter after we register the blocks
remove_filter( 'plugins_url', __NAMESPACE__ . '\filter_plugins_url', 10, 2 );
}

/**
* Filter the plugins_url to allow us to use assets from theme.
*
* @param string $url The plugins url
* @param string $path The path to the asset.
*
* @return string The overridden url to the block asset.
*/
function filter_plugins_url( $url, $path ) {
$file = preg_replace( '/\.\.\//', '', $path );
return trailingslashit( get_stylesheet_directory_uri() ) . $file;
}


/**
* Enqueue editor-only JavaScript/CSS for blocks.
*
Expand Down
41 changes: 22 additions & 19 deletions projects/10up-theme/includes/blocks/example-block/block.json
Original file line number Diff line number Diff line change
@@ -1,35 +1,35 @@
{
"title": "Example Block",
"description": "An Example Block",
"text-domain": "tenup-scaffold",
"textdomain": "tenup-scaffold",
"name": "tenup/example",
"icon": "feedback",
"category": "tenup-scaffold-blocks",
"attributes":{
"icon": "feedback",
"category": "tenup-scaffold-blocks",
"attributes": {
"customTitle": {
"type" : "string"
"type": "string"
}
},
"example": {
"attributes":{
"customTitle": "Example Block"
}
},
"supports": {
},
"example": {
"attributes": {
"customTitle": "Example Block"
}
},
"supports": {
"align": false,
"alignWide": false,
"anchor": false,
"color":{
"color": {
"gradients": false,
"background": false,
"text": false
},
"customClassName": false,
"defaultStylePicker": false,
"typography": {
"fontSize": false,
"lineHeight": true
},
"typography": {
"fontSize": false,
"lineHeight": true
},
"html": false,
"inserter": true,
"multiple": true,
Expand All @@ -38,6 +38,9 @@
"padding": false
}
},
"editorScript": "file:../../../dist/blocks/example-block/editor.js",
"editorStyle": "file:../../../dist/blocks/example-block/editor.css"
"editorScript": "file:./index.js",
"editorStyle": "file:./editor.css",
"style": "file:./style.css",
"viewScript": "file:./view.js",
"script": "file:./script.js"
}
Empty file.
Loading