Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ function createEsm2AmdExportsBridges(projectDir, buildConfig, manifest) {
const {exports, output} = buildConfig;

exports.forEach((exportItem) => {
const {pkgName, scope} = splitModuleName(exportItem.name);
const splittedModuleName = splitModuleName(exportItem.name);
const {pkgName, scope} = splittedModuleName;
let {modulePath} = splittedModuleName;

// Compute src and destination package.json objects

const scopedPkgName = joinModuleName(scope, pkgName, '');

Expand All @@ -42,15 +46,21 @@ function createEsm2AmdExportsBridges(projectDir, buildConfig, manifest) {
basedir: projectDir,
}
));
const srcPkgId = `${srcPkgJson.name}@${srcPkgJson.version}`;

const pkgJson = {
dependencies: {},
main: './index.js',
name: addNamespace(scopedPkgName, rootPkgJson),
version: srcPkgJson.version,
};
const pkgId = `${pkgJson.name}@${pkgJson.version}`;

// Tweak module path and package.json main's field

if (!modulePath) {
modulePath = '/index';
pkgJson.main = './index.js';
}

// Create output package dir

const packageDir = path.join(
output,
Expand All @@ -61,6 +71,16 @@ function createEsm2AmdExportsBridges(projectDir, buildConfig, manifest) {
})
);

fs.mkdirSync(packageDir, {recursive: true});

// Create/update output package.json file

fs.writeFileSync(
path.join(packageDir, 'package.json'),
JSON.stringify(pkgJson, null, '\t'),
'utf8'
);

//
// Compute the relative position of the bridge related to the real ES
// module.
Expand All @@ -71,18 +91,34 @@ function createEsm2AmdExportsBridges(projectDir, buildConfig, manifest) {
// Also, depending for npm-scoped scoped packages, and additional folder
// level appears under `/o/js/resolved-module/...`.
//
// Also, for internal module paths, we must add more `../`s.
//

let rootDir = '../..';

if (exportItem.name.startsWith('@')) {
rootDir += '/..';
}

const hopsToAdd = modulePath.split('/').length - 1;

for (let i = 0; i < hopsToAdd; i++) {
rootDir += '/..';
}

rootDir += webContextPath;

const rootDir = exportItem.name.startsWith('@')
? `../../../..${webContextPath}`
: `../../..${webContextPath}`;
// Create output bridge file

const pkgId = `${pkgJson.name}@${pkgJson.version}`;

const bridgeSource = `
import * as esModule from "${rootDir}/__liferay__/exports/${flattenPkgName(
exportItem.name
)}.js";

Liferay.Loader.define(
"${pkgId}/index",
"${pkgId}${modulePath}",
['module'],
function (module) {
module.exports = {
Expand All @@ -94,39 +130,40 @@ Liferay.Loader.define(
);
`;

fs.mkdirSync(packageDir, {recursive: true});

fs.writeFileSync(
path.join(packageDir, 'package.json'),
JSON.stringify(pkgJson, null, '\t'),
'utf8'
const outputFilePath = path.join(
packageDir,
`${modulePath.substr(1).replace('/', path.sep)}.js`
);

fs.writeFileSync(
path.join(packageDir, 'index.js'),
bridgeSource,
'utf8'
);
fs.mkdirSync(path.dirname(outputFilePath), {recursive: true});

manifest.packages[pkgId] = manifest.packages[pkgId] || {
dest: {
dir: '.',
id: pkgId,
name: pkgJson.name,
version: pkgJson.version,
},
modules: {
'index.js': {
flags: {
esModule: true,
useESM: true,
},
fs.writeFileSync(outputFilePath, bridgeSource, 'utf8');

// Update output manifest.json

if (!manifest.packages[pkgId]) {
const srcPkgId = `${srcPkgJson.name}@${srcPkgJson.version}`;

manifest.packages[pkgId] = {
dest: {
dir: '.',
id: pkgId,
name: pkgJson.name,
version: pkgJson.version,
},
},
src: {
id: srcPkgId,
name: srcPkgJson.name,
version: srcPkgJson.version,
modules: {},
src: {
id: srcPkgId,
name: srcPkgJson.name,
version: srcPkgJson.version,
},
};
}

manifest.packages[pkgId].modules[`${modulePath.substr(1)}.js`] = {
flags: {
esModule: true,
useESM: true,
},
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

/* eslint-disable @liferay/no-dynamic-require */

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const path = require('path');
const resolve = require('resolve');
const TerserPlugin = require('terser-webpack-plugin');
Expand Down Expand Up @@ -40,13 +41,16 @@ module.exports = async function runWebpackAsBundler(
await runWebpack(indexWebpackConfig, buildConfig.report);
}

const webpackConfigs = getImportsWebpackConfigs(buildConfig);
const exportsWebpackConfig = getExportsWebpackConfig(
projectDir,
buildConfig
);

let i = 0;

for (const webpackConfig of webpackConfigs) {
for (const webpackConfig of exportsWebpackConfig) {
createTempFile(
`webpackAsBundler.import[${i++}].config.json`,
`webpackAsBundler.export[${i++}].config.json`,
JSON.stringify(webpackConfig, null, 2),
{autoDelete: false}
);
Expand Down Expand Up @@ -261,7 +265,7 @@ ${nonDefaultFields}
};
}

function getImportsWebpackConfigs(buildConfig) {
function getExportsWebpackConfig(projectDir, buildConfig) {
const {exports, imports} = buildConfig;

const allExternals = convertImportsToExternals(imports, 3);
Expand All @@ -277,9 +281,19 @@ function getImportsWebpackConfigs(buildConfig) {

delete externals[pkgName];

// Compute output file name: for the case of .css files, we want webpack
// to create a .js file with the same name as the CSS file and next to
// its output. That file is never used (as webpack leaves it empty), but
// it allows our exports CSS loader to put the valid .js stub in the
// proper place (__liferay__/exports).

const entryKey = importPath.endsWith('.css')
? `__liferay__/css/${flatPkgName.replace(/\.css$/, '')}`
: `__liferay__/exports/${flatPkgName}`;

const webpackConfig = {
entry: {
[`__liferay__/exports/${flatPkgName}`]: {
[entryKey]: {
import: importPath,
},
},
Expand Down Expand Up @@ -327,13 +341,40 @@ function getImportsWebpackConfigs(buildConfig) {
},
path: path.resolve(buildConfig.output),
},
plugins: [new MiniCssExtractPlugin()],
resolve: {
fallback: {
path: false,
},
},
};

// For CSS exports, add our loader so that the .js stub is created

if (importPath.endsWith('.css')) {
webpackConfig.module.rules.push({
include: /node_modules/,
test: new RegExp(`${importPath.replace('/', '\\/')}$`),
use: [
{
loader: require.resolve('./webpackExportCssLoader'),
options: {
filename:
entryKey.replace('/css/', '/exports/') + '.css',
projectDir,
url: entryKey + '.css',
},
},
{
loader: MiniCssExtractPlugin.loader,
},
{
loader: require.resolve('css-loader'),
},
],
});
}

if (process.env.NODE_ENV === 'development') {
webpackConfig.devtool = 'source-map';
webpackConfig.mode = 'development';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* SPDX-FileCopyrightText: © 2019 Liferay, Inc. <https://liferay.com>
* SPDX-License-Identifier: BSD-3-Clause
*/

/* eslint-disable @liferay/no-dynamic-require */

const getBndWebContextPath = require('./getBndWebContextPath');

module.exports = function (content, _map, _meta) {
const {filename, projectDir, url} = this.getOptions();

const webContextPath = getBndWebContextPath(projectDir);

this.emitFile(
filename + '.js',
`
const link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute('type', 'text/css');
link.setAttribute(
'href',
Liferay.ThemeDisplay.getPathContext() + '/o${webContextPath}/${url}'
);
document.querySelector('head').appendChild(link);
`
);

return content;
};