Replace webpack+babel with esbuild (#6230)
* Replace webpack+babel with esbuild
This commit is contained in:
Родитель
83e163afb4
Коммит
fb8b2d7faf
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* This is not technically a "config", but the actual run script that
|
||||
* invokes ESBuild (https://esbuild.github.io) on the various libraries
|
||||
* that we need bundled and written to our frontend's js directory.
|
||||
*
|
||||
* As a normal script, this should be invoked using node, and it can
|
||||
* take a runtime argument `--node-env` followed by either the string
|
||||
* "production" or "development" so that process.env.NODE_ENV in our
|
||||
* code gets interpreted correctly.
|
||||
*/
|
||||
const { build } = require(`esbuild`);
|
||||
const path = require(`path`);
|
||||
|
||||
const arg = process.argv.indexOf(`--node-env`);
|
||||
const mode =
|
||||
arg > 0 ? process.argv[arg + 1] : process.env.NODE_ENV || `development`;
|
||||
const inProduction = mode === `production`;
|
||||
|
||||
const inDir = `./source/js/`;
|
||||
const outDir = `./network-api/networkapi/frontend/_js/`;
|
||||
|
||||
const sources = [
|
||||
`main.js`,
|
||||
`foundation/pages/mozfest/index.js`,
|
||||
`foundation/pages/directory-listing-filters.js`,
|
||||
`buyers-guide/bg-main.js`,
|
||||
`polyfills.js`,
|
||||
];
|
||||
|
||||
const base = {
|
||||
bundle: true,
|
||||
watch: !inProduction,
|
||||
sourcemap: !inProduction,
|
||||
minify: inProduction,
|
||||
loader: {
|
||||
".js": "jsx",
|
||||
".jsx": "jsx",
|
||||
},
|
||||
define: {
|
||||
"process.env.NODE_ENV": JSON.stringify(mode),
|
||||
},
|
||||
inject: [`esbuild.react.shim.js`],
|
||||
};
|
||||
|
||||
sources.map((source) => {
|
||||
const opts = Object.assign({}, base);
|
||||
opts.entryPoints = [`${inDir}${source}`];
|
||||
opts.outfile = `${outDir}${path
|
||||
.basename(source)
|
||||
.replace(`.js`, `.compiled.js`)}`;
|
||||
return build(opts);
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
import * as React from "react";
|
||||
|
||||
/**
|
||||
* In order for ESBuild to correctly resolve the React.createElement()
|
||||
* function that babel "auto injects" when it transfroms JSX, we need
|
||||
* the following shim that ensures that any file that relies on React
|
||||
* has the variable "React" available for use.
|
||||
*
|
||||
* See https://esbuild.github.io/content-types/#auto-import-for-jsx
|
||||
*/
|
||||
|
||||
export { React };
|
|
@ -3,8 +3,11 @@ jQuery( () => {
|
|||
///////////////
|
||||
|
||||
const tabbedContent = $(`form .tab-content`);
|
||||
const topLevel = (tabbedContent.length > 0) ? tabbedContent.first() : $(`.content form`);
|
||||
const languageCodeRegex = new RegExp(' \\[('+wagtailModelTranslations.languages.join('|')+')\\]');
|
||||
const topLevel =
|
||||
tabbedContent.length > 0 ? tabbedContent.first() : $(`.content form`);
|
||||
const languageCodeRegex = new RegExp(
|
||||
" \\[(" + wagtailModelTranslations.languages.join("|") + ")\\]"
|
||||
);
|
||||
|
||||
if (topLevel.length === 0) {
|
||||
// obviously, if we don't have an element to attach
|
||||
|
@ -27,7 +30,7 @@ jQuery( () => {
|
|||
if (res === null) return;
|
||||
|
||||
var code = res[0],
|
||||
locale = code.replace(/[ \[\]]/g,'');
|
||||
locale = code.replace(/[ \[\]]/g, "");
|
||||
|
||||
// Verify this is a known locale and not a fluke,
|
||||
// using the global "wagtailModelTranslations.languages"
|
||||
|
@ -37,7 +40,7 @@ jQuery( () => {
|
|||
if (wagtailModelTranslations.languages.indexOf(locale) === -1) return;
|
||||
|
||||
// Check if it's a LI for inlines
|
||||
if ($(element).has('ul.multiple').length) return;
|
||||
if ($(element).has("ul.multiple").length) return;
|
||||
|
||||
// We do our show/hiding based on list items,
|
||||
// otherwise we're just "emptying" a list item
|
||||
|
@ -74,8 +77,12 @@ jQuery( () => {
|
|||
* will always stay visible.
|
||||
*/
|
||||
function buildSets(topElement) {
|
||||
$(`li.object:not(.multi-field), div.field`, topElement).each( filterForLocale );
|
||||
document.dispatchEvent(new CustomEvent('wagtail-modeltranslation:buildSets:done'));
|
||||
$(`li.object:not(.multi-field), div.field`, topElement).each(
|
||||
filterForLocale
|
||||
);
|
||||
document.dispatchEvent(
|
||||
new CustomEvent("wagtail-modeltranslation:buildSets:done")
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -83,7 +90,7 @@ jQuery( () => {
|
|||
*/
|
||||
function getSelectedLocales() {
|
||||
var selectedLocales = [];
|
||||
$('.showing-locale').each(function() {
|
||||
$(".showing-locale").each(function () {
|
||||
selectedLocales.push($(this).text());
|
||||
});
|
||||
return selectedLocales;
|
||||
|
@ -92,15 +99,15 @@ jQuery( () => {
|
|||
/**
|
||||
* Adds event listeners on click for inlines.
|
||||
*/
|
||||
$('a[id^=id_][id$=-ADD]').click(e => {
|
||||
$("a[id^=id_][id$=-ADD]").click((e) => {
|
||||
e.preventDefault();
|
||||
// get the ul where all inlines will be added
|
||||
ulForms = $(e.currentTarget).parent().siblings('ul.multiple')[0];
|
||||
ulForms = $(e.currentTarget).parent().siblings("ul.multiple")[0];
|
||||
// register new fields in sets
|
||||
buildSets(ulForms);
|
||||
// remove visibility class for selected locales
|
||||
selectedLocales = getSelectedLocales();
|
||||
selectedLocales.forEach( locale => {
|
||||
selectedLocales.forEach((locale) => {
|
||||
toggleLocale(locale, true);
|
||||
});
|
||||
});
|
||||
|
@ -110,17 +117,21 @@ jQuery( () => {
|
|||
* visibility for each locale's fields.
|
||||
*/
|
||||
function buildLocaleToggler() {
|
||||
var bar = $(`<div class="locale-picker"><h2>${wagtailModelTranslations.viewEditString}</h2></div>`);
|
||||
var bar = $(
|
||||
`<div class="locale-picker"><h2>${wagtailModelTranslations.viewEditString}</h2></div>`
|
||||
);
|
||||
var ul = $(`<ul class="locales"></ul>`);
|
||||
bar.append(ul);
|
||||
|
||||
var toggles = {};
|
||||
locales.forEach( locale => {
|
||||
var li = $(`<li class="locale"><button class="locale-toggle">${locale}</button></li>`);
|
||||
locales.forEach((locale) => {
|
||||
var li = $(
|
||||
`<li class="locale"><button class="locale-toggle">${locale}</button></li>`
|
||||
);
|
||||
ul.append(li);
|
||||
|
||||
$(`button.locale-toggle`, li).each((index, toggle) => {
|
||||
toggle.addEventListener(`click`, e => {
|
||||
toggle.addEventListener(`click`, (e) => {
|
||||
e.preventDefault();
|
||||
toggle.classList.toggle(`showing-locale`);
|
||||
toggleLocale(locale);
|
||||
|
@ -145,10 +156,10 @@ jQuery( () => {
|
|||
var action = `toggle`;
|
||||
|
||||
if (state !== undefined) {
|
||||
action = state ? `remove` : `add`
|
||||
action = state ? `remove` : `add`;
|
||||
}
|
||||
|
||||
localisedElements[locale].forEach(element => {
|
||||
localisedElements[locale].forEach((element) => {
|
||||
element.classList[action](`l10n-hidden`);
|
||||
});
|
||||
}
|
||||
|
@ -156,7 +167,9 @@ jQuery( () => {
|
|||
var default_locale = wagtailModelTranslations.defaultLanguage;
|
||||
var localisedElements = {};
|
||||
var columnCSS = [`field-col`];
|
||||
for (var i=1; i<=12; i++) { columnCSS.push(`col${i}`); }
|
||||
for (var i = 1; i <= 12; i++) {
|
||||
columnCSS.push(`col${i}`);
|
||||
}
|
||||
|
||||
// Build the sets that track which fields
|
||||
// belong to which language code.
|
||||
|
|
|
@ -38,12 +38,16 @@ sync.addEventListener(`click`, () => {
|
|||
// there any errors? If so, we need to immediately reveal all fields.
|
||||
if (document.querySelectorAll(`p.error-message`).length !== 0) {
|
||||
showAll.click();
|
||||
document.dispatchEvent(new CustomEvent(`wagtailcustomization:copy-helper:done`));
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(`wagtailcustomization:copy-helper:done`)
|
||||
);
|
||||
}
|
||||
|
||||
// If we kicked in before the localization interface JS kicked in: listen for
|
||||
// its "I am done" event so we can reveal fields once it's safe to do so.
|
||||
document.addEventListener(`wagtail-modeltranslation:buildSets:done`, evt => {
|
||||
document.addEventListener(`wagtail-modeltranslation:buildSets:done`, (evt) => {
|
||||
showAll.click();
|
||||
document.dispatchEvent(new CustomEvent(`wagtailcustomization:copy-helper:done`));
|
||||
document.dispatchEvent(
|
||||
new CustomEvent(`wagtailcustomization:copy-helper:done`)
|
||||
);
|
||||
});
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
40
package.json
40
package.json
|
@ -6,16 +6,17 @@
|
|||
"node": ">=14.4.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build:common": "shx rm -rf network-api/networkapi/frontend && shx mkdir -p network-api/networkapi/frontend/_js && run-p build:images build:sass && npm run build:contribute",
|
||||
"build": "run-s build:clean && run-p build:js:prod build:common",
|
||||
"build:clean": "shx rm -rf network-api/networkapi/frontend && shx mkdir -p network-api/networkapi/frontend/_js",
|
||||
"build:common": "run-p build:images build:sass build:contribute",
|
||||
"build:contribute": "shx cp contribute.json network-api/networkapi/frontend/",
|
||||
"build:dev": "run-s build:common build:js:dev",
|
||||
"build:images": "shx rm -rf network-api/networkapi/frontend/_images && shx cp -r source/images network-api/networkapi/frontend/_images",
|
||||
"build:js-uncompressed": "npm run build:js:dev",
|
||||
"build:js": "webpack --mode=production",
|
||||
"build:js:dev": "webpack --mode=development",
|
||||
"build:sass": "shx mkdir -p network-api/networkapi/frontend/_css && sass source/sass/main.scss network-api/networkapi/frontend/_css/main.compiled.css && sass source/sass/buyers-guide/bg-main.scss network-api/networkapi/frontend/_css/buyers-guide.compiled.css && npm run optimize:css",
|
||||
"build": "run-s build:common build:js",
|
||||
"build-uncompressed": "run-s build:common build:js-uncompressed",
|
||||
"build:js:dev": "node esbuild.config.js -- --node-env development",
|
||||
"build:js:prod": "node esbuild.config.js -- --node-env production",
|
||||
"build:sass": "run-s build:sass:clean && run-p build:sass:main build:sass:bg && run-s optimize:css",
|
||||
"build:sass:clean": "shx mkdir -p network-api/networkapi/frontend/_css",
|
||||
"build:sass:main": "sass source/sass/main.scss network-api/networkapi/frontend/_css/main.compiled.css",
|
||||
"build:sass:bg": "sass source/sass/buyers-guide/bg-main.scss network-api/networkapi/frontend/_css/buyers-guide.compiled.css",
|
||||
"cypress": "run-p --race cypress:docker cypress:test",
|
||||
"cypress:a11y": "run-p --race cypress:docker cypress:test:a11y",
|
||||
"cypress:ci": "run-p --race server cypress:test",
|
||||
|
@ -29,19 +30,21 @@
|
|||
"fix:js": "npm run test:eslint:js -- --fix",
|
||||
"fix:scss": "npm run test:scss -- --fix",
|
||||
"heroku-postbuild": "npm run build",
|
||||
"optimize:css": "postcss network-api/networkapi/frontend/_css/*.css --dir network-api/networkapi/frontend/_css",
|
||||
"optimize:css": "run-s optimize:css:*",
|
||||
"optimize:css:run": "postcss network-api/networkapi/frontend/_css/*.css --dir network-api/networkapi/frontend/_css/temp",
|
||||
"optimize:css:copy": "shx mv network-api/networkapi/frontend/_css/temp/* network-api/networkapi/frontend/_css",
|
||||
"optimize:css:clean": "shx rm -rf network-api/networkapi/frontend/_css/temp",
|
||||
"optimize:svg": "svgo --multipass --folder ./source/images/ --recursive",
|
||||
"optimize:jpg": "find source/images -type f -name '*.jpg' -print0 | xargs -0 -n 1 -P 6 -I '{}' guetzli --quality 93 '{}' '{}'",
|
||||
"optimize:png": "find source/images -type f -name '*.png' -print0 | xargs -0 -n 1 -P 6 optipng",
|
||||
"optimize": "run-p optimize:**",
|
||||
"percy": "percy exec -t 800 -- npm run cypress:ci",
|
||||
"precommit": "prettier \"source/js/**/*.js\" \"source/js/**/*.jsx\" webpack.config.js --write",
|
||||
"prestatus": "echo test",
|
||||
"precommit": "prettier \"source/js/**/*.js\" \"source/js/**/*.jsx\" *.config.js --write",
|
||||
"server": "python network-api/manage.py runserver 0.0.0.0:8000",
|
||||
"start": "docker-compose up",
|
||||
"test:procfile": "node test/test-procfile.js",
|
||||
"test:eslint:js:pre": "prettier \"cypress/integration/*.js\" \"source/js/**/*.js\" \"source/js/**/*.jsx\" \"network-api/networkapi/wagtailcustomization/**/*.js\" webpack.config.js --write",
|
||||
"test:eslint:js": "eslint --config ./.eslintrc.json \"cypress/integration/*.js\" \"source/js/**/*.js\" \"source/js/**/*.jsx\" \"network-api/networkapi/wagtailcustomization/**/*.js\" webpack.config.js",
|
||||
"test:eslint:js:pre": "prettier \"cypress/integration/*.js\" \"source/js/**/*.js\" \"source/js/**/*.jsx\" \"network-api/networkapi/wagtailcustomization/**/*.js\" ./*.js --write",
|
||||
"test:eslint:js": "eslint --config ./.eslintrc.json \"cypress/integration/*.js\" \"source/js/**/*.js\" \"source/js/**/*.jsx\" \"network-api/networkapi/wagtailcustomization/**/*.js\" ./*.js",
|
||||
"test:eslint:a11y:pre": "prettier \"source/js/**/*.jsx\" --write",
|
||||
"test:eslint:a11y": "eslint --config ./.eslintrc.a11y.json \"source/js/**/*.jsx\"",
|
||||
"test:scss:pre": "prettier \"source/sass/**/*.scss\" \"source/js/**/*.scss\" \"network-api/networkapi/{,!(frontend)/**/}*.css\" --write",
|
||||
|
@ -49,9 +52,8 @@
|
|||
"test:scss:styleguide:color": "stylelint \"source/sass/**/*.scss\" \"source/js/**/*.scss\" \"!source/sass/**/_colors.scss\" --syntax scss --config .stylelintrc-colors.js",
|
||||
"test:css": "stylelint \"network-api/networkapi/{,!(frontend)/**/}*.css\" --syntax scss",
|
||||
"test": "run-s test:** build",
|
||||
"watch": "npm run build:dev && run-p watch:**",
|
||||
"watch": "run-s build:clean && run-p build:js:dev build:common watch:**",
|
||||
"watch:images": "chokidar \"source/images/**/*\" -c \"npm run build:images\"",
|
||||
"watch:js": "chokidar \"source/js/**/*.js\" \"source/js/**/*.jsx\" -c \"npm run build:js-uncompressed\"",
|
||||
"watch:sass": "chokidar \"source/**/*.scss\" -c \"npm run build:sass\""
|
||||
},
|
||||
"browserslist": [
|
||||
|
@ -61,17 +63,13 @@
|
|||
"author": "Mozilla",
|
||||
"license": "MPL-2.0",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.12.10",
|
||||
"@babel/preset-env": "^7.13.0",
|
||||
"@babel/preset-react": "^7.12.10",
|
||||
"@sentry/browser": "^6.0.3",
|
||||
"autoprefixer": "^10.2.4",
|
||||
"axe-core": "^4.1.1",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-loader": "^8.2.2",
|
||||
"bootstrap": "^4.6.0",
|
||||
"classnames": "2.2.6",
|
||||
"cssnano": "^4.1.10",
|
||||
"esbuild": "^0.8.46",
|
||||
"event-stream": "3.3.4",
|
||||
"js-cookie": "2.2.1",
|
||||
"moment": "^2.29.1",
|
||||
|
@ -86,8 +84,6 @@
|
|||
"sass": "^1.32.5",
|
||||
"shx": "^0.3.3",
|
||||
"uuid": "^8.3.2",
|
||||
"webpack": "^5.19.0",
|
||||
"webpack-cli": "^4.5.0",
|
||||
"whatwg-fetch": "^3.5.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -1,17 +1,21 @@
|
|||
let commonPlugins = [
|
||||
require('autoprefixer'),
|
||||
];
|
||||
let commonPlugins = [require("autoprefixer")];
|
||||
|
||||
let prodPlugins = [
|
||||
require('cssnano')({
|
||||
preset: ['default', {
|
||||
require("cssnano")({
|
||||
preset: [
|
||||
"default",
|
||||
{
|
||||
discardComments: {
|
||||
removeAll: true,
|
||||
},
|
||||
}]
|
||||
})
|
||||
},
|
||||
],
|
||||
}),
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
plugins: process.env.NODE_ENV === 'production' ? commonPlugins.concat(prodPlugins) : commonPlugins
|
||||
plugins:
|
||||
process.env.NODE_ENV === "production"
|
||||
? commonPlugins.concat(prodPlugins)
|
||||
: commonPlugins,
|
||||
};
|
||||
|
|
|
@ -9,18 +9,16 @@ export default (apps) => {
|
|||
const targetNode = document.querySelector(
|
||||
`#multipage-nav-mobile .container .row .col-12`
|
||||
);
|
||||
const multipageLinks = document.querySelectorAll(`#multipage-nav a`)
|
||||
const multipageLinks = document.querySelectorAll(`#multipage-nav a`);
|
||||
|
||||
if (targetNode && multipageLinks.length) {
|
||||
let links = Array.from(multipageLinks).map(
|
||||
(link) => {
|
||||
let links = Array.from(multipageLinks).map((link) => {
|
||||
return {
|
||||
label: link.textContent.trim(),
|
||||
href: link.getAttribute(`href`),
|
||||
isActive: !!link.getAttribute(`class`).match(/active/),
|
||||
};
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
apps.push(
|
||||
new Promise((resolve) => {
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
export default () => {
|
||||
const summaryBlock = document.querySelector(".article-navbar-container");
|
||||
if (summaryBlock) {
|
||||
const marginOffset = window.getComputedStyle(summaryBlock).getPropertyValue(
|
||||
"--top-offset"
|
||||
);
|
||||
const marginOffset = window
|
||||
.getComputedStyle(summaryBlock)
|
||||
.getPropertyValue("--top-offset");
|
||||
const dropDownMenu = document.querySelector(".article-summary-menu");
|
||||
const articleSummaryToggle = document.querySelector(
|
||||
".article-summary-toggle"
|
||||
|
@ -33,7 +33,7 @@ export default () => {
|
|||
}
|
||||
},
|
||||
{
|
||||
passive: true
|
||||
passive: true,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -408,7 +408,11 @@
|
|||
@include hover-focus-active {
|
||||
/* stylelint-disable */
|
||||
// This is a one-off color.
|
||||
background: rgb(231, 231, 252); // One-off colors; no variable exists for this
|
||||
background: rgb(
|
||||
231,
|
||||
231,
|
||||
252
|
||||
); // One-off colors; no variable exists for this
|
||||
/* stylelint-enable */
|
||||
text-decoration: none;
|
||||
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
let webpack = require(`webpack`);
|
||||
let path = require(`path`);
|
||||
let frontendPath = path.resolve(
|
||||
__dirname,
|
||||
`network-api`,
|
||||
`networkapi`,
|
||||
`frontend`,
|
||||
`_js`
|
||||
);
|
||||
|
||||
let rules = [
|
||||
{
|
||||
test: /\.js(x?)$/,
|
||||
exclude: /node_modules/,
|
||||
loader: `babel-loader`,
|
||||
options: {
|
||||
presets: [
|
||||
[`@babel/preset-env`, { targets: `> 1%, last 2 versions` }],
|
||||
[`@babel/preset-react`, { runtime: "automatic" }],
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
let main = {
|
||||
devtool: false,
|
||||
entry: {
|
||||
main: `./source/js/main.js`,
|
||||
mozfest: `./source/js/foundation/pages/mozfest/index.js`,
|
||||
"directory-listing-filters": `./source/js/foundation/pages/directory-listing-filters.js`,
|
||||
},
|
||||
output: {
|
||||
path: frontendPath,
|
||||
filename: `[name].compiled.js`,
|
||||
},
|
||||
module: {
|
||||
rules,
|
||||
},
|
||||
plugins: [new webpack.EnvironmentPlugin(["NODE_ENV"])],
|
||||
};
|
||||
|
||||
let bgMain = {
|
||||
devtool: false,
|
||||
entry: {
|
||||
"bg-main": `./source/js/buyers-guide/bg-main.js`,
|
||||
polyfills: `./source/js/polyfills.js`,
|
||||
},
|
||||
output: {
|
||||
path: frontendPath,
|
||||
filename: `[name].compiled.js`,
|
||||
},
|
||||
module: {
|
||||
rules,
|
||||
},
|
||||
};
|
||||
|
||||
let config = [main, bgMain];
|
||||
|
||||
module.exports = (env, argv) => {
|
||||
process.env.NODE_ENV = process.env.NODE_ENV || argv.mode;
|
||||
|
||||
return config;
|
||||
};
|
Загрузка…
Ссылка в новой задаче