Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
3 changes: 3 additions & 0 deletions .github/workflows/eslint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ jobs:

- name: Run ESLint
run: yarn run eslint . --report-unused-disable-directives

- name: Run Jest
run: yarn run jest
59 changes: 59 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,65 @@ All notable changes to this project will be documented in this file. Dates are d

Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).

#### [2.11.1](https://github.com/magesuite/magepack/compare/2.11.0...2.11.1)

> 25 October 2022

- Improve AMD module detection [`#164`](https://github.com/magesuite/magepack/pull/164)
- Update CHANGELOG [`1c4fcf2`](https://github.com/magesuite/magepack/commit/1c4fcf2a44286415ee63538b69c9508c6098b70f)
- Release 2.11.1 [`3db79bf`](https://github.com/magesuite/magepack/commit/3db79bfc786fcc01b45d8f4330c8f37ef9e1d442)

#### [2.11.0](https://github.com/magesuite/magepack/compare/2.10.1...2.11.0)

> 24 October 2022

- Correct detection of anonymous AMD modules [`#142`](https://github.com/magesuite/magepack/pull/142)
- Block magepack during 'generate' command [`#151`](https://github.com/magesuite/magepack/pull/151)
- Run Jest test suite in GitHub Action [`#160`](https://github.com/magesuite/magepack/pull/160)
- Update CHANGELOG [`476e995`](https://github.com/magesuite/magepack/commit/476e99556b0fb2148c506096940c6cad9c2d9486)
- Release 2.11.0 [`772dde2`](https://github.com/magesuite/magepack/commit/772dde220b5c394f7ff30f9e57261639c9c16a75)

#### [2.10.1](https://github.com/magesuite/magepack/compare/2.10.0...2.10.1)

> 19 October 2022

- Fix generate-sourcemap package version [`#141`](https://github.com/magesuite/magepack/issues/141)
- Update CHANGELOG [`b1debc0`](https://github.com/magesuite/magepack/commit/b1debc007ecadcb0c2072c55316b06a8bb77a3de)
- Release 2.10.1 [`34e6495`](https://github.com/magesuite/magepack/commit/34e64956076966c37de608f3e35cff67bed1cbb7)
- Remove unused snapshot [`be38c09`](https://github.com/magesuite/magepack/commit/be38c09dee7b4333c68c79bfb5dc3f2fe4659617)

#### [2.10.0](https://github.com/magesuite/magepack/compare/2.9.0...2.10.0)

> 19 October 2022

- Improve anonymous module detection [`#140`](https://github.com/magesuite/magepack/issues/140)
- Update CHANGELOG [`e72e852`](https://github.com/magesuite/magepack/commit/e72e852968f0af97169c76694eb36b1351673f7b)
- Release 2.10.0 [`1f01cf9`](https://github.com/magesuite/magepack/commit/1f01cf947341e9ab135eae8cfb9132cd67de278b)

#### [2.9.0](https://github.com/magesuite/magepack/compare/2.8.0...2.9.0)

> 19 October 2022

- Update terser [`b96eecc`](https://github.com/magesuite/magepack/commit/b96eeccd3605d6fcfac8d4cc26445c3b0072990f)
- Remove promise wait [`fbf033a`](https://github.com/magesuite/magepack/commit/fbf033ab91573c80f244e25692a7f4f72bc09236)
- Update CHANGELOG.md [`081ceaf`](https://github.com/magesuite/magepack/commit/081ceaf6bf9bc1ea0176d752094fdb9419a43600)

#### [2.8.0](https://github.com/magesuite/magepack/compare/2.7.2...2.8.0)

> 4 February 2022

- Add options to generate source-maps and minify output irrespective of Magento 2 JS minification setting [`#132`](https://github.com/magesuite/magepack/pull/132)
- Update README.md [`43105d8`](https://github.com/magesuite/magepack/commit/43105d85d643920f96309bc2f0c198cf7016472c)
- Release 2.8.0 [`7b6dc1c`](https://github.com/magesuite/magepack/commit/7b6dc1c05fd89d8a29a72420002f3080f145c0dc)

#### [2.7.2](https://github.com/magesuite/magepack/compare/2.7.1...2.7.2)

> 6 September 2021

- Update CHANGELOG.md [`c409b72`](https://github.com/magesuite/magepack/commit/c409b72447371e13cd5350ed76c3ea3e01f5995a)
- Fix linting errors [`bb42986`](https://github.com/magesuite/magepack/commit/bb429869b933d79d2bfcd5998926e95d9cf663c5)
- Release 2.7.2 [`e4cfbef`](https://github.com/magesuite/magepack/commit/e4cfbef79a08c2311f4c73aaec1c9bf49e9646a0)

#### [2.7.1](https://github.com/magesuite/magepack/compare/2.7.0...2.7.1)

> 6 September 2021
Expand Down
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,23 @@ magepack bundle

This command will iterate over each deployed locale (excluding Magento/blank) and prepare bundles for each of them.

There are two optional params you can set:
There are multiple optional params you can set:

`-c, --config` - defining the configuration file path, in case you have multiple configuration files (e.g multiple themes with individual configuration files)

`-g, --glob` - defining where to look for locales to bundle.

`-s, --sourcemap` - enables sourcemap generation for bundled js.

`-m, --minify` - overrides Magento 2 JS minification setting, minifying the bundle using Terser (used by default if Magento 2 JS minification is enabled).

#### Sourcemaps

It is possible to enable sourcemaps for bundled JS files, using the `-s, --sourcemap` flag with `magepack bundle` command. However, there are couple of caveats:

* It does not respect existing sourcemaps for individual JS files (possible future update)
* For sourcemaps to be meaningful, Magento 2 JS minification must be **turned off**. This is because Magento 2 does not (and cannot with current PHP implementation) generate sourcemaps for each minified JS file. For this reason, a separate `-m, --minify` flag exists to minify the resulting bundle using Terser.

### Enabling

Once you made sure [Magepack Magento module](https://github.com/magesuite/magepack-magento) is installed, what is left is to enable it via admin panel under Stores->Configuration->Advanced->Developer or CLI:
Expand Down
11 changes: 9 additions & 2 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,19 @@ program
)
.option('-g, --glob <path>', 'Glob pattern of themes to bundle.')
.option('-d, --debug', 'Enable logging of debugging information.')
.action(({ config, debug, glob }) => {
.option('-s, --sourcemap', 'Include sourcemaps with generated bundles')
.option(
'-m, --minify',
'Minify bundle using terser irrespective of Magento 2 minification setting'
)
.action(({ config, sourcemap, minify, debug, glob }) => {
if (debug) {
logger.level = 5;
}

require('./lib/bundle')(config, glob).catch(errorHandler);
require('./lib/bundle')(config, glob, sourcemap, minify).catch(
errorHandler
);
});

program.parse(process.argv);
96 changes: 70 additions & 26 deletions lib/bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const path = require('path');
const { stringify } = require('javascript-stringify');
const terser = require('terser');
const gzipSize = require('gzip-size');
const genSourceMap = require('generate-sourcemap');

const logger = require('./utils/logger');
const getLocales = require('./bundle/getLocales');
Expand All @@ -11,7 +12,12 @@ const checkMinifyOn = require('./bundle/checkMinifyOn');
const moduleWrapper = require('./bundle/moduleWrapper');
const modulePathMapper = require('./bundle/moduleMapResolver');

module.exports = async (bundlingConfigPath, localesGlobPattern) => {
module.exports = async (
bundlingConfigPath,
localesGlobPattern,
includeSourcemaps = false,
forceMinify = false
) => {
const bundlingConfigRealPath = path.resolve(bundlingConfigPath);

logger.info(`Using bundling config from "${bundlingConfigRealPath}".`);
Expand All @@ -22,10 +28,10 @@ module.exports = async (bundlingConfigPath, localesGlobPattern) => {

const isMinifyOn = checkMinifyOn(localesPaths);

localesPaths.forEach((localePath) => {
localesPaths.forEach(async (localePath) => {
logger.info(`Creating bundles for "${localePath}".`);

bundlingConfig.forEach((bundle) => {
bundlingConfig.forEach(async (bundle) => {
const bundleName = bundle.name;

logger.debug(`Creating bundle "${bundleName}".`);
Expand All @@ -37,9 +43,22 @@ module.exports = async (bundlingConfigPath, localesGlobPattern) => {
);

const pathMapper = modulePathMapper(localePath, isMinifyOn);
const bundleFileName = path.basename(bundlePath);
const bundlePathDir = path.dirname(bundlePath);

if (!fs.existsSync(bundlePathDir)) {
fs.mkdirSync(path.dirname(bundlePath), {
recursive: true,
});
}

let bundleContents = '';
const bundledModules = [];
const sourceMapRanges = [];
const sourceRange = {
start: 0,
end: 0,
};

logger.debug(`Collecting modules for "${bundleName}".`);

Expand Down Expand Up @@ -76,8 +95,17 @@ module.exports = async (bundlingConfigPath, localesGlobPattern) => {
);
}

sourceRange.end =
sourceRange.start +
moduleContents.split(/\r?\n/).length;
bundleContents += moduleContents + '\n';
bundledModules.push(moduleName);
sourceMapRanges.push({
sourceFile: path.relative(bundlePathDir, modulePath),
start: sourceRange.start,
end: sourceRange.end,
});
sourceRange.start = sourceRange.end;
} catch (error) {
logger.debug(
`Module "${moduleName}", not found under "${modulePath}".`
Expand All @@ -87,26 +115,40 @@ module.exports = async (bundlingConfigPath, localesGlobPattern) => {

logger.debug(`Bundle "${bundleName}" collected.`);

if (isMinifyOn) {
const sourceMap = genSourceMap(bundleFileName);
sourceMap.addRanges(sourceMapRanges);

if (isMinifyOn || forceMinify) {
logger.debug(`Minifying "${bundleName}" bundle.`);

const { code, error: minificationError } = terser.minify(
bundleContents,
{
output: {
comments: false,
},
mangle: {
reserved: [
'$',
'jQuery',
'define',
'require',
'exports',
],
},
}
);
const terserConfig = {
output: {
comments: false,
},
mangle: {
reserved: [
'$',
'jQuery',
'define',
'require',
'exports',
],
},
};

if (includeSourcemaps) {
terserConfig.sourceMap = {
content: sourceMap.getMap(),
filename: bundleFileName,
url: `${bundleFileName}.map`,
};
}

const {
code,
map,
error: minificationError,
} = await terser.minify(bundleContents, terserConfig);

if (minificationError) {
logger.error(minificationError);
Expand All @@ -115,17 +157,19 @@ module.exports = async (bundlingConfigPath, localesGlobPattern) => {
bundleContents = code;

logger.debug(`Bundle "${bundleName}" minified.`);

if (includeSourcemaps) {
fs.writeFileSync(`${bundlePath}.map`, map);
}
} else if (includeSourcemaps) {
bundleContents += `\n//# sourceMappingURL=${bundleFileName}.map\n`;
fs.writeFileSync(`${bundlePath}.map`, sourceMap.getMap());
}

logger.debug(
`Writing "${bundleName}" bundle and configuration to disk.`
);

const bundlePathDir = path.dirname(bundlePath);
if (!fs.existsSync(bundlePathDir)) {
fs.mkdirSync(path.dirname(bundlePath), { recursive: true });
}

fs.writeFileSync(bundlePath, bundleContents);

const bundleOptions = {
Expand Down
2 changes: 0 additions & 2 deletions lib/bundle/__snapshots__/moduleWrapper.test.js.snap
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`moduleWrapper module wrapAnonymousAmd output matches snapshot 1`] = `"define('foo', [], function() {});"`;

exports[`moduleWrapper module wrapNonAmd output matches snapshot 1`] = `
"define('name', (require.s.contexts._.config.shim['name'] && require.s.contexts._.config.shim['name'].deps || []), function() {

Expand Down
11 changes: 8 additions & 3 deletions lib/bundle/moduleWrapper.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ const jsesc = require('jsesc');
*
* @param {string} moduleContents Contents of the module.
*/
const isNonAmd = (moduleContents) => !moduleContents.match(/define\s*\(/m);
const isNonAmd = (moduleContents) =>
!moduleContents.match(/(^|[?;\s{}()])define\s*\(/m);

/**
* Wraps non-AMD module so it can be safely inlined into the bundle.
Expand Down Expand Up @@ -50,7 +51,8 @@ const wrapText = (moduleName, content) => {
* @param {string} moduleContents Contents of the module to wrap.
*/
const isAnonymousAmd = (moduleContents) =>
!moduleContents.match(/define\s*\(\s*['"]/m);
!isNonAmd(moduleContents) &&
!moduleContents.match(/(^|[?;\s{}()])define\s*\(\s*['"]/m);

/**
* Changes anonymous AMD module into the named one to be able to bundle it.
Expand All @@ -59,7 +61,10 @@ const isAnonymousAmd = (moduleContents) =>
* @param {string} moduleContents Contents of the module to wrap.
*/
const wrapAnonymousAmd = (moduleName, moduleContents) =>
moduleContents.replace(/define\s*\(/m, `define('${moduleName}', `);
moduleContents.replace(
/(^|[?;\s{}()])define\s*\(/m,
`$1define('${moduleName}', `
);

module.exports = {
isNonAmd,
Expand Down
Loading