Skip to content

Commit

Permalink
feat: expose PARAGON_VERSION as a global variable
Browse files Browse the repository at this point in the history
  • Loading branch information
adamstankiewicz committed May 28, 2023
1 parent a21bbed commit 49b201a
Show file tree
Hide file tree
Showing 17 changed files with 2,396 additions and 57 deletions.
1 change: 1 addition & 0 deletions config/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module.exports = {
},
globals: {
newrelic: false,
PARAGON: false,
},
ignorePatterns: [
'module.config.js',
Expand Down
108 changes: 108 additions & 0 deletions config/data/paragonUtils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
const path = require('path');
const fs = require('fs');

/**
* Attempts to extract the Paragon version from the `node_modules` of
* the consuming application.
*
* @param {string} dir Path to directory containing `node_modules`.
* @returns {string} Paragon dependency version of the consuming application
*/
function getParagonVersion(dir) {
const pathToPackageJson = `${dir}/node_modules/@edx/paragon/package.json`;
if (!fs.existsSync(pathToPackageJson)) {
return undefined;
}
return JSON.parse(fs.readFileSync(pathToPackageJson)).version;
}

/**
* TODO
*/
function getParagonThemeCss(dir) {
const pathToCoreCss = `${dir}/node_modules/@edx/paragon/dist/core.min.css`;
const pathToThemeVariantLightCss = `${dir}/node_modules/@edx/paragon/dist/light.min.css`;

const coreCssExists = fs.existsSync(pathToCoreCss);
const themeVariantLightCssExists = fs.existsSync(pathToThemeVariantLightCss);

if (!coreCssExists || !themeVariantLightCssExists) {
return undefined;
}

const coreResult = {
filePath: path.resolve(__dirname, pathToCoreCss),
entryName: 'paragonThemeCoreCss',
outputChunkName: 'paragon-theme-core',
};
const themeVariantResults = {
light: {
filePath: path.resolve(__dirname, pathToThemeVariantLightCss),
entryName: 'paragonThemeVariantLightCss',
outputChunkName: 'paragon-theme-variant-light',
},
};

return {
core: fs.existsSync(pathToCoreCss) ? coreResult : undefined,
variants: {
light: fs.existsSync(pathToThemeVariantLightCss) ? themeVariantResults.light : undefined,
},
};
}

/**
* TODO
*/
function getParagonCacheGroups(paragonThemeCss) {
const cacheGroups = {};
if (!paragonThemeCss) {
return cacheGroups;
}
const getCacheGroupName = (module, _, cacheGroupKey) => {
const buildHash = module.buildInfo.hash;
const moduleFileName = module
.identifier()
.split('/')
.reduceRight((item) => item)
.split('|')[0]
.split('.css')[0];
const outputChunkFilename = `${cacheGroupKey}.${buildHash}.${moduleFileName}`;
return outputChunkFilename;
};

cacheGroups[paragonThemeCss.core.entryName] = {
type: 'css/mini-extract',
name: getCacheGroupName,
chunks: chunk => chunk.name === paragonThemeCss.core.entryName,
enforce: true,
};
cacheGroups[paragonThemeCss.variants.light.entryName] = {
type: 'css/mini-extract',
name: getCacheGroupName,
chunks: chunk => chunk.name === paragonThemeCss.variants.light.entryName,
enforce: true,
};

return cacheGroups;
}

function getParagonEntryPoints(paragonThemeCss) {
const entryPoints = {};
if (!paragonThemeCss) {
return entryPoints;
}
entryPoints[paragonThemeCss.core.entryName] = path.resolve(process.cwd(), paragonThemeCss.core.filePath);
entryPoints[paragonThemeCss.variants.light.entryName] = path.resolve(
process.cwd(),
paragonThemeCss.variants.light.filePath,
);
return entryPoints;
}

module.exports = {
getParagonVersion,
getParagonThemeCss,
getParagonCacheGroups,
getParagonEntryPoints,
};
10 changes: 10 additions & 0 deletions config/jest/setupTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,13 @@ const testEnvFile = path.resolve(process.cwd(), '.env.test');
if (fs.existsSync(testEnvFile)) {
dotenv.config({ path: testEnvFile });
}

global.PARAGON = {
version: '1.0.0',
themeUrls: {
core: 'core.min.css',
variants: {
light: 'light.min.css',
},
},
};
23 changes: 23 additions & 0 deletions config/webpack.common.config.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
const path = require('path');
const RemoveEmptyScriptsPlugin = require('webpack-remove-empty-scripts');

const ParagonWebpackPlugin = require('../lib/plugins/paragon-webpack-plugin/ParagonWebpackPlugin');
const {
getParagonThemeCss,
getParagonCacheGroups,
getParagonEntryPoints,
} = require('./data/paragonUtils');

const paragonThemeCss = getParagonThemeCss(process.cwd());

module.exports = {
entry: {
app: path.resolve(process.cwd(), './src/index'),
...getParagonEntryPoints(paragonThemeCss),
},
output: {
path: path.resolve(process.cwd(), './dist'),
Expand All @@ -19,4 +30,16 @@ module.exports = {
},
extensions: ['.js', '.jsx'],
},
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
...getParagonCacheGroups(paragonThemeCss),
},
},
},
plugins: [
new RemoveEmptyScriptsPlugin(),
new ParagonWebpackPlugin(),
],
};
1 change: 1 addition & 0 deletions config/webpack.dev-stage.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ module.exports = merge(commonConfig, {
new HtmlWebpackPlugin({
inject: true, // Appends script tags linking to the webpack bundles at the end of the body
template: path.resolve(process.cwd(), 'public/index.html'),
chunks: ['app'],
FAVICON_URL: process.env.FAVICON_URL || null,
OPTIMIZELY_PROJECT_ID: process.env.OPTIMIZELY_PROJECT_ID || null,
NODE_ENV: process.env.NODE_ENV || null,
Expand Down
93 changes: 60 additions & 33 deletions config/webpack.dev.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// This is the dev Webpack config. All settings here should prefer a fast build
// time at the expense of creating larger, unoptimized bundles.
const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin');

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssNano = require('cssnano');
const { merge } = require('webpack-merge');
const Dotenv = require('dotenv-webpack');
const dotenv = require('dotenv');
Expand Down Expand Up @@ -31,6 +32,49 @@ resolvePrivateEnvConfig('.env.private');
const aliases = getLocalAliases();
const PUBLIC_PATH = process.env.PUBLIC_PATH || '/';

function getStyleUseConfig({ isMinified = false } = {}) {
const postCssPlugins = [
PostCssAutoprefixerPlugin(),
PostCssRTLCSS(),
PostCssCustomMediaCSS(),
];
if (isMinified) {
postCssPlugins.push(CssNano());
}
return [
{
loader: 'css-loader', // translates CSS into CommonJS
options: {
sourceMap: true,
modules: {
compileType: 'icss',
},
},
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: postCssPlugins,
},
},
},
'resolve-url-loader',
{
loader: 'sass-loader', // compiles Sass to CSS
options: {
sourceMap: true,
sassOptions: {
includePaths: [
path.join(process.cwd(), 'node_modules'),
path.join(process.cwd(), 'src'),
],
},
},
},
];
}

module.exports = merge(commonConfig, {
mode: 'development',
devtool: 'eval-source-map',
Expand Down Expand Up @@ -68,41 +112,19 @@ module.exports = merge(commonConfig, {
// flash-of-unstyled-content issues in development.
{
test: /(.scss|.css)$/,
use: [
'style-loader', // creates style nodes from JS strings
oneOf: [
{
loader: 'css-loader', // translates CSS into CommonJS
options: {
sourceMap: true,
modules: {
compileType: 'icss',
},
},
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
PostCssAutoprefixerPlugin(),
PostCssRTLCSS(),
PostCssCustomMediaCSS(),
],
},
},
resource: /paragon/,
use: [
MiniCssExtractPlugin.loader,
...getStyleUseConfig({ isMinified: true }),
],
},
'resolve-url-loader',
{
loader: 'sass-loader', // compiles Sass to CSS
options: {
sourceMap: true,
sassOptions: {
includePaths: [
path.join(process.cwd(), 'node_modules'),
path.join(process.cwd(), 'src'),
],
},
},
use: [
'style-loader', // creates style nodes from JS strings
...getStyleUseConfig(),
],
},
],
},
Expand Down Expand Up @@ -154,10 +176,15 @@ module.exports = merge(commonConfig, {
},
// Specify additional processing or side-effects done on the Webpack output bundles as a whole.
plugins: [
// Writes the extracted CSS from each entry to a file in the output directory.
new MiniCssExtractPlugin({
filename: '[name].css',
}),
// Generates an HTML file in the output directory.
new HtmlWebpackPlugin({
inject: true, // Appends script tags linking to the webpack bundles at the end of the body
template: path.resolve(process.cwd(), 'public/index.html'),
chunks: ['app'],
FAVICON_URL: process.env.FAVICON_URL || null,
OPTIMIZELY_PROJECT_ID: process.env.OPTIMIZELY_PROJECT_ID || null,
NODE_ENV: process.env.NODE_ENV || null,
Expand Down
3 changes: 2 additions & 1 deletion config/webpack.prod.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ module.exports = merge(commonConfig, {
plugins: [
PostCssAutoprefixerPlugin(),
PostCssRTLCSS(),
CssNano(),
PostCssCustomMediaCSS(),
CssNano(),
...extraPostCssPlugins,
],
},
Expand Down Expand Up @@ -201,6 +201,7 @@ module.exports = merge(commonConfig, {
new HtmlWebpackPlugin({
inject: true, // Appends script tags linking to the webpack bundles at the end of the body
template: path.resolve(process.cwd(), 'public/index.html'),
chunks: ['app'],
FAVICON_URL: process.env.FAVICON_URL || null,
OPTIMIZELY_PROJECT_ID: process.env.OPTIMIZELY_PROJECT_ID || null,
NODE_ENV: process.env.NODE_ENV || null,
Expand Down
1 change: 1 addition & 0 deletions example/.env.development
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
BASE_URL='http://localhost:8080'
FAVICON_URL=https://edx-cdn.org/v3/default/favicon.ico
TEST_VARIABLE='foo'
Loading

0 comments on commit 49b201a

Please sign in to comment.