Replace to shakapacker from webpacker

This commit is contained in:
Yamagishi Kazutoshi 2022-05-09 17:57:57 +00:00
parent 0aacf00f5b
commit 64ee565b33
80 changed files with 1737 additions and 3956 deletions

View File

@ -4,4 +4,6 @@ not IE 11
not dead not dead
[development] [development]
supports es6-module last 1 chrome version
last 1 firefox version
last 1 safari version

View File

@ -65,7 +65,7 @@ jobs:
- install-ruby-dependencies: - install-ruby-dependencies:
ruby-version: '3.0' ruby-version: '3.0'
- node/install-packages: - node/install-packages:
cache-version: v1 cache-version: v2
pkg-manager: yarn pkg-manager: yarn
- run: - run:
command: ./bin/rails assets:precompile command: ./bin/rails assets:precompile
@ -214,7 +214,7 @@ workflows:
requires: requires:
- build - build
- node/run: - node/run:
cache-version: v1 cache-version: v2
name: test-webui name: test-webui
pkg-manager: yarn pkg-manager: yarn
requires: requires:

View File

@ -8,10 +8,6 @@ module.exports = {
jest: true, jest: true,
}, },
globals: {
ATTACHMENT_HOST: false,
},
parser: '@babel/eslint-parser', parser: '@babel/eslint-parser',
plugins: [ plugins: [

3
.gitignore vendored
View File

@ -59,7 +59,8 @@ npm-debug.log
# Ignore yarn log files # Ignore yarn log files
yarn-error.log yarn-error.log
yarn-debug.log yarn-debug.log*
.yarn-integrity
# Ignore vagrant log files # Ignore vagrant log files
*-cloudimg-console.log *-cloudimg-console.log

View File

@ -44,3 +44,4 @@ Gruntfile.js
# for specific ignore # for specific ignore
!.svgo.yml !.svgo.yml
!sass-lint/**/*.yml !sass-lint/**/*.yml
!shakapacker/**/*.yml

View File

@ -84,13 +84,13 @@ gem 'sidekiq-unique-jobs', '~> 7.1'
gem 'sidekiq-bulk', '~> 0.2.0' gem 'sidekiq-bulk', '~> 0.2.0'
gem 'simple-navigation', '~> 4.4' gem 'simple-navigation', '~> 4.4'
gem 'simple_form', '~> 5.1' gem 'simple_form', '~> 5.1'
gem 'shakapacker', '~> 6.5'
gem 'sprockets-rails', '~> 3.4', require: 'sprockets/railtie' gem 'sprockets-rails', '~> 3.4', require: 'sprockets/railtie'
gem 'stoplight', '~> 3.0.0' gem 'stoplight', '~> 3.0.0'
gem 'strong_migrations', '~> 0.7' gem 'strong_migrations', '~> 0.7'
gem 'tty-prompt', '~> 0.23', require: false gem 'tty-prompt', '~> 0.23', require: false
gem 'twitter-text', '~> 3.1.0' gem 'twitter-text', '~> 3.1.0'
gem 'tzinfo-data', '~> 1.2022' gem 'tzinfo-data', '~> 1.2022'
gem 'webpacker', '~> 5.4'
gem 'webpush', git: 'https://github.com/ClearlyClaire/webpush.git', ref: 'f14a4d52e201128b1b00245d11b6de80d6cfdcd9' gem 'webpush', git: 'https://github.com/ClearlyClaire/webpush.git', ref: 'f14a4d52e201128b1b00245d11b6de80d6cfdcd9'
gem 'webauthn', '~> 2.5' gem 'webauthn', '~> 2.5'

View File

@ -496,7 +496,7 @@ GEM
httpclient httpclient
json-jwt (>= 1.11.0) json-jwt (>= 1.11.0)
rack (>= 2.1.0) rack (>= 2.1.0)
rack-proxy (0.7.0) rack-proxy (0.7.2)
rack rack
rack-test (2.0.2) rack-test (2.0.2)
rack (>= 1.3) rack (>= 1.3)
@ -610,6 +610,11 @@ GEM
activerecord (>= 4.0.0) activerecord (>= 4.0.0)
railties (>= 4.0.0) railties (>= 4.0.0)
semantic_range (3.0.0) semantic_range (3.0.0)
shakapacker (6.5.2)
activesupport (>= 5.2)
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
sidekiq (6.5.6) sidekiq (6.5.6)
connection_pool (>= 2.2.5) connection_pool (>= 2.2.5)
rack (~> 2.0) rack (~> 2.0)
@ -714,11 +719,6 @@ GEM
addressable (>= 2.8.0) addressable (>= 2.8.0)
crack (>= 0.3.2) crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0) hashdiff (>= 0.4.0, < 2.0.0)
webpacker (5.4.3)
activesupport (>= 5.2)
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
websocket-driver (0.7.5) websocket-driver (0.7.5)
websocket-extensions (>= 0.1.0) websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5) websocket-extensions (0.1.5)
@ -833,6 +833,7 @@ DEPENDENCIES
ruby-progressbar (~> 1.11) ruby-progressbar (~> 1.11)
sanitize (~> 6.0) sanitize (~> 6.0)
scenic (~> 1.6) scenic (~> 1.6)
shakapacker (~> 6.5)
sidekiq (~> 6.5) sidekiq (~> 6.5)
sidekiq-bulk (~> 0.2.0) sidekiq-bulk (~> 0.2.0)
sidekiq-scheduler (~> 4.0) sidekiq-scheduler (~> 4.0)
@ -851,6 +852,5 @@ DEPENDENCIES
tzinfo-data (~> 1.2022) tzinfo-data (~> 1.2022)
webauthn (~> 2.5) webauthn (~> 2.5)
webmock (~> 3.18) webmock (~> 3.18)
webpacker (~> 5.4)
webpush! webpush!
xorcist (~> 1.1) xorcist (~> 1.1)

View File

@ -1,4 +1,4 @@
web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb web: env PORT=3000 RAILS_ENV=development bundle exec puma -C config/puma.rb
sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq sidekiq: env PORT=3000 RAILS_ENV=development bundle exec sidekiq
stream: env PORT=4000 yarn run start stream: env PORT=4000 yarn run start
webpack: ./bin/webpack-dev-server --listen-host 0.0.0.0 webpack: env WEBPACKER_DEV_SERVER_HOST=0.0.0.0 ./bin/webpacker-dev-server

View File

@ -2,7 +2,7 @@
module MascotHelper module MascotHelper
def mascot_url def mascot_url
full_asset_url(instance_presenter.mascot&.file&.url || asset_pack_path('media/images/elephant_ui_plane.svg')) full_asset_url(instance_presenter.mascot&.file&.url || asset_pack_path('static/elephant_ui_plane.svg'))
end end
private private

View File

@ -1,11 +1,11 @@
import './public-path'; import 'mastodon/public-path';
import loadPolyfills from '../mastodon/load_polyfills'; import loadPolyfills from 'mastodon/load_polyfills';
import { start } from '../mastodon/common'; import { start } from 'mastodon/common';
start(); start();
function loaded() { function loaded() {
const TimelineContainer = require('../mastodon/containers/timeline_container').default; const TimelineContainer = require('mastodon/containers/timeline_container').default;
const React = require('react'); const React = require('react');
const ReactDOM = require('react-dom'); const ReactDOM = require('react-dom');
const mountNode = document.getElementById('mastodon-timeline'); const mountNode = document.getElementById('mastodon-timeline');
@ -17,7 +17,7 @@ function loaded() {
} }
function main() { function main() {
const ready = require('../mastodon/ready').default; const ready = require('mastodon/ready').default;
ready(loaded); ready(loaded);
} }

View File

@ -1,6 +1,6 @@
import './public-path'; import 'mastodon/public-path';
import { delegate } from '@rails/ujs'; import { delegate } from '@rails/ujs';
import ready from '../mastodon/ready'; import ready from 'mastodon/ready';
const batchCheckboxClassName = '.batch-checkbox input[type="checkbox"]'; const batchCheckboxClassName = '.batch-checkbox input[type="checkbox"]';
@ -170,8 +170,8 @@ ready(() => {
const componentName = element.getAttribute('data-admin-component'); const componentName = element.getAttribute('data-admin-component');
const { locale, ...componentProps } = JSON.parse(element.getAttribute('data-props')); const { locale, ...componentProps } = JSON.parse(element.getAttribute('data-props'));
import('../mastodon/containers/admin_component').then(({ default: AdminComponent }) => { import('mastodon/containers/admin_component').then(({ default: AdminComponent }) => {
return import('../mastodon/components/admin/' + componentName).then(({ default: Component }) => { return import('mastodon/components/admin/' + componentName).then(({ default: Component }) => {
ReactDOM.render(( ReactDOM.render((
<AdminComponent locale={locale}> <AdminComponent locale={locale}>
<Component {...componentProps} /> <Component {...componentProps} />

View File

@ -0,0 +1,11 @@
import 'mastodon/public-path';
import loadPolyfills from 'mastodon/load_polyfills';
import { start } from 'mastodon/common';
start();
loadPolyfills().then(() => {
require('mastodon/main').default();
}).catch(e => {
console.error(e);
});

View File

@ -1,5 +1,5 @@
import './public-path'; import 'mastodon/public-path';
import ready from '../mastodon/ready'; import ready from 'mastodon/ready';
ready(() => { ready(() => {
const image = document.querySelector('img'); const image = document.querySelector('img');

3
app/javascript/mailer.js Normal file
View File

@ -0,0 +1,3 @@
require('./styles/mailer.scss');
require.context('./icons');

View File

@ -1,4 +1,4 @@
import Rails from '@rails/ujs'; import * as Rails from '@rails/ujs';
export function start() { export function start() {
require('font-awesome/css/font-awesome.css'); require('font-awesome/css/font-awesome.css');

View File

@ -39,6 +39,7 @@ function main() {
console.error(err); console.error(err);
}); });
} }
perf.stop('main()'); perf.stop('main()');
}); });
} }

View File

@ -1,6 +1,6 @@
import IntlMessageFormat from 'intl-messageformat'; import IntlMessageFormat from 'intl-messageformat';
import locales from './web_push_locales';
import { unescape } from 'lodash'; import { unescape } from 'lodash';
import locales from './web_push_locales';
const MAX_NOTIFICATIONS = 5; const MAX_NOTIFICATIONS = 5;
const GROUP_TAG = 'tag'; const GROUP_TAG = 'tag';

View File

@ -1,11 +0,0 @@
import './public-path';
import loadPolyfills from '../mastodon/load_polyfills';
import { start } from '../mastodon/common';
start();
loadPolyfills().then(() => {
require('../mastodon/main').default();
}).catch(e => {
console.error(e);
});

View File

@ -1,3 +0,0 @@
require('../styles/mailer.scss');
require.context('../icons');

View File

@ -1,10 +1,10 @@
import './public-path'; import 'mastodon/public-path';
import escapeTextContentForBrowser from 'escape-html';
import loadPolyfills from '../mastodon/load_polyfills';
import ready from '../mastodon/ready';
import { start } from '../mastodon/common';
import loadKeyboardExtensions from '../mastodon/load_keyboard_extensions';
import 'cocoon-js-vanilla'; import 'cocoon-js-vanilla';
import escapeTextContentForBrowser from 'escape-html';
import loadPolyfills from 'mastodon/load_polyfills';
import ready from 'mastodon/ready';
import { start } from 'mastodon/common';
import loadKeyboardExtensions from 'mastodon/load_keyboard_extensions';
start(); start();
@ -26,10 +26,10 @@ window.addEventListener('message', e => {
function main() { function main() {
const IntlMessageFormat = require('intl-messageformat').default; const IntlMessageFormat = require('intl-messageformat').default;
const { timeAgoString } = require('../mastodon/components/relative_timestamp'); const { timeAgoString } = require('mastodon/components/relative_timestamp');
const { delegate } = require('@rails/ujs'); const { delegate } = require('@rails/ujs');
const emojify = require('../mastodon/features/emoji/emoji').default; const emojify = require('mastodon/features/emoji/emoji').default;
const { getLocale } = require('../mastodon/locales'); const { getLocale } = require('mastodon/locales');
const { messages } = getLocale(); const { messages } = getLocale();
const React = require('react'); const React = require('react');
const ReactDOM = require('react-dom'); const ReactDOM = require('react-dom');
@ -90,7 +90,7 @@ function main() {
const reactComponents = document.querySelectorAll('[data-component]'); const reactComponents = document.querySelectorAll('[data-component]');
if (reactComponents.length > 0) { if (reactComponents.length > 0) {
import(/* webpackChunkName: "containers/media_container" */ '../mastodon/containers/media_container') import(/* webpackChunkName: "containers/media_container" */ 'mastodon/containers/media_container')
.then(({ default: MediaContainer }) => { .then(({ default: MediaContainer }) => {
[].forEach.call(reactComponents, (component) => { [].forEach.call(reactComponents, (component) => {
[].forEach.call(component.children, (child) => { [].forEach.call(component.children, (child) => {

View File

@ -1,11 +1,11 @@
import './public-path'; import 'mastodon/public-path';
import loadPolyfills from '../mastodon/load_polyfills'; import loadPolyfills from 'mastodon/load_polyfills';
import { start } from '../mastodon/common'; import { start } from 'mastodon/common';
start(); start();
function loaded() { function loaded() {
const ComposeContainer = require('../mastodon/containers/compose_container').default; const ComposeContainer = require('mastodon/containers/compose_container').default;
const React = require('react'); const React = require('react');
const ReactDOM = require('react-dom'); const ReactDOM = require('react-dom');
const mountNode = document.getElementById('mastodon-compose'); const mountNode = document.getElementById('mastodon-compose');
@ -17,7 +17,7 @@ function loaded() {
} }
function main() { function main() {
const ready = require('../mastodon/ready').default; const ready = require('mastodon/ready').default;
ready(loaded); ready(loaded);
} }

View File

@ -164,7 +164,7 @@ $small-breakpoint: 960px;
td { td {
padding: 8px; padding: 8px;
align-self: start; align-self: start;
align-items: start; align-items: flex-start;
word-break: break-all; word-break: break-all;
&.nowrap { &.nowrap {

View File

@ -1758,7 +1758,7 @@ a.account__display-name {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: flex; display: flex;
align-items: center; align-items: flex-center;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
scrollbar-width: none; /* Firefox */ scrollbar-width: none; /* Firefox */
@ -2619,7 +2619,7 @@ a.account__display-name {
.column-actions { .column-actions {
display: flex; display: flex;
align-items: start; align-items: flex-start;
justify-content: center; justify-content: center;
padding: 40px; padding: 40px;
padding-top: 40px; padding-top: 40px;

View File

@ -1,7 +1,7 @@
import axios from 'axios';
import * as WebAuthnJSON from '@github/webauthn-json';
import ready from '../mastodon/ready';
import 'regenerator-runtime/runtime'; import 'regenerator-runtime/runtime';
import * as WebAuthnJSON from '@github/webauthn-json';
import axios from 'axios';
import ready from 'mastodon/ready';
function getCSRFToken() { function getCSRFToken() {
var CSRFSelector = document.querySelector('meta[name="csrf-token"]'); var CSRFSelector = document.querySelector('meta[name="csrf-token"]');

View File

@ -32,7 +32,7 @@ class ManifestSerializer < ActiveModel::Serializer
def icons def icons
ICON_SIZES.map do |size| ICON_SIZES.map do |size|
{ {
src: full_pack_url("media/icons/android-chrome-#{size}x#{size}.png"), src: full_pack_url("static/android-chrome-#{size}x#{size}.png"),
sizes: "#{size}x#{size}", sizes: "#{size}x#{size}",
type: 'image/png', type: 'image/png',
} }

View File

@ -39,7 +39,7 @@ class REST::InstanceSerializer < ActiveModel::Serializer
end end
def thumbnail def thumbnail
instance_presenter.thumbnail ? full_asset_url(instance_presenter.thumbnail.file.url) : full_pack_url('media/images/preview.png') instance_presenter.thumbnail ? full_asset_url(instance_presenter.thumbnail.file.url) : full_pack_url('static/preview.png')
end end
def stats def stats

View File

@ -9,7 +9,7 @@
.column-0 .column-0
.public-account-header.public-account-header--no-bar .public-account-header.public-account-header--no-bar
.public-account-header__image .public-account-header__image
= image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('media/images/preview.png'), alt: @instance_presenter.site_title, class: 'parallax' = image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('static/preview.png'), alt: @instance_presenter.site_title, class: 'parallax'
.column-1 .column-1
.landing-page__call-to-action{ dir: 'ltr' } .landing-page__call-to-action{ dir: 'ltr' }
@ -25,7 +25,7 @@
%span= t 'about.status_count_after', count: @instance_presenter.status_count %span= t 'about.status_count_after', count: @instance_presenter.status_count
.row__mascot .row__mascot
.landing-page__mascot .landing-page__mascot
= image_tag @instance_presenter.mascot&.file&.url || asset_pack_path('media/images/elephant_ui_plane.svg'), alt: '' = image_tag @instance_presenter.mascot&.file&.url || asset_pack_path('static/elephant_ui_plane.svg'), alt: ''
.column-2 .column-2
.contact-widget .contact-widget

View File

@ -53,7 +53,7 @@
.hero-widget .hero-widget
.hero-widget__img .hero-widget__img
= image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('media/images/preview.png'), alt: @instance_presenter.site_title = image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('static/preview.png'), alt: @instance_presenter.site_title
.hero-widget__text .hero-widget__text
%p %p

View File

@ -1,6 +1,6 @@
.hero-widget .hero-widget
.hero-widget__img .hero-widget__img
= image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('media/images/preview.png'), alt: @instance_presenter.site_title = image_tag @instance_presenter.hero&.file&.url || @instance_presenter.thumbnail&.file&.url || asset_pack_path('static/preview.png'), alt: @instance_presenter.site_title
.hero-widget__text .hero-widget__text
%p= @instance_presenter.site_short_description.html_safe.presence || t('about.about_mastodon_html') %p= @instance_presenter.site_short_description.html_safe.presence || t('about.about_mastodon_html')

View File

@ -14,12 +14,12 @@
%link{ rel: 'icon', href: '/favicon.ico', type: 'image/x-icon' }/ %link{ rel: 'icon', href: '/favicon.ico', type: 'image/x-icon' }/
- %w(16 32 48).each do |size| - %w(16 32 48).each do |size|
%link{ rel: 'icon', sizes: "#{size}x#{size}", href: asset_pack_path("media/icons/favicon-#{size}x#{size}.png"), type: 'image/png' }/ %link{ rel: 'icon', sizes: "#{size}x#{size}", href: asset_pack_path("static/favicon-#{size}x#{size}.png"), type: 'image/png' }/
- %w(57 60 72 76 114 120 144 152 167 180 1024).each do |size| - %w(57 60 72 76 114 120 144 152 167 180 1024).each do |size|
%link{ rel: 'apple-touch-icon', sizes: "#{size}x#{size}", href: asset_pack_path("media/icons/apple-touch-icon-#{size}x#{size}.png") }/ %link{ rel: 'apple-touch-icon', sizes: "#{size}x#{size}", href: asset_pack_path("static/apple-touch-icon-#{size}x#{size}.png") }/
%link{ rel: 'mask-icon', href: asset_pack_path('media/images/logo-symbol-icon.svg'), color: '#6364FF' }/ %link{ rel: 'mask-icon', href: asset_pack_path('static/logo-symbol-icon.svg'), color: '#6364FF' }/
%link{ rel: 'manifest', href: manifest_path(format: :json) }/ %link{ rel: 'manifest', href: manifest_path(format: :json) }/
%meta{ name: 'theme-color', content: '#6364FF' }/ %meta{ name: 'theme-color', content: '#6364FF' }/
%meta{ name: 'apple-mobile-web-app-capable', content: 'yes' }/ %meta{ name: 'apple-mobile-web-app-capable', content: 'yes' }/

View File

@ -24,7 +24,7 @@
%tr %tr
%td.column-cell %td.column-cell
= link_to root_url do = link_to root_url do
= image_tag full_pack_url('media/images/mailer/wordmark.png'), alt: 'Mastodon', height: 34, class: 'logo' = image_tag full_pack_url('static/mailer/wordmark.png'), alt: 'Mastodon', height: 34, class: 'logo'
= yield = yield
@ -49,4 +49,4 @@
%p= link_to t('application_mailer.notification_preferences'), settings_preferences_notifications_url %p= link_to t('application_mailer.notification_preferences'), settings_preferences_notifications_url
%td.column-cell.text-right %td.column-cell.text-right
= link_to root_url do = link_to root_url do
= image_tag full_pack_url('media/images/mailer/logo.png'), alt: 'Mastodon', height: 24 = image_tag full_pack_url('static/mailer/logo.png'), alt: 'Mastodon', height: 24

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_grade.png'), alt:'' = image_tag full_pack_url('static/mailer/icon_grade.png'), alt:''
%h1= t 'notification_mailer.favourite.title' %h1= t 'notification_mailer.favourite.title'
%p.lead= t('notification_mailer.favourite.body', name: @account.pretty_acct) %p.lead= t('notification_mailer.favourite.body', name: @account.pretty_acct)

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_person_add.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_person_add.png'), alt: ''
%h1= t 'notification_mailer.follow.title' %h1= t 'notification_mailer.follow.title'
%p.lead= t('notification_mailer.follow.body', name: @account.pretty_acct) %p.lead= t('notification_mailer.follow.body', name: @account.pretty_acct)

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_person_add.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_person_add.png'), alt: ''
%h1= t 'notification_mailer.follow_request.title' %h1= t 'notification_mailer.follow_request.title'
%p.lead= t('notification_mailer.follow_request.body', name: @account.pretty_acct) %p.lead= t('notification_mailer.follow_request.body', name: @account.pretty_acct)

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_reply.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_reply.png'), alt: ''
%h1= t 'notification_mailer.mention.title' %h1= t 'notification_mailer.mention.title'
%p.lead= t('notification_mailer.mention.body', name: @status.account.pretty_acct) %p.lead= t('notification_mailer.mention.body', name: @status.account.pretty_acct)

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_cached.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_cached.png'), alt: ''
%h1= t 'notification_mailer.reblog.title' %h1= t 'notification_mailer.reblog.title'
%p.lead= t('notification_mailer.reblog.body', name: @account.pretty_acct) %p.lead= t('notification_mailer.reblog.body', name: @account.pretty_acct)

View File

@ -8,7 +8,7 @@
= opengraph 'og:type', 'website' = opengraph 'og:type', 'website'
= opengraph 'og:title', @instance_presenter.site_title = opengraph 'og:title', @instance_presenter.site_title
= opengraph 'og:description', description = opengraph 'og:description', description
= opengraph 'og:image', full_asset_url(thumbnail&.file&.url || asset_pack_path('media/images/preview.png', protocol: :request)) = opengraph 'og:image', full_asset_url(thumbnail&.file&.url || asset_pack_path('static/preview.png', protocol: :request))
= opengraph 'og:image:width', thumbnail ? thumbnail.meta['width'] : '1200' = opengraph 'og:image:width', thumbnail ? thumbnail.meta['width'] : '1200'
= opengraph 'og:image:height', thumbnail ? thumbnail.meta['height'] : '630' = opengraph 'og:image:height', thumbnail ? thumbnail.meta['height'] : '630'
= opengraph 'twitter:card', 'summary_large_image' = opengraph 'twitter:card', 'summary_large_image'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_done.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_done.png'), alt: ''
%h1= t 'user_mailer.appeal_approved.title' %h1= t 'user_mailer.appeal_approved.title'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_warning.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_warning.png'), alt: ''
%h1= t 'user_mailer.appeal_rejected.title' %h1= t 'user_mailer.appeal_rejected.title'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_file_download.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_file_download.png'), alt: ''
%h1= t 'user_mailer.backup_ready.title' %h1= t 'user_mailer.backup_ready.title'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_email.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_email.png'), alt: ''
%h1= t 'devise.mailer.confirmation_instructions.title' %h1= t 'devise.mailer.confirmation_instructions.title'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_email.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_email.png'), alt: ''
%h1= t 'devise.mailer.email_changed.title' %h1= t 'devise.mailer.email_changed.title'
%p.lead= t 'devise.mailer.email_changed.explanation' %p.lead= t 'devise.mailer.email_changed.explanation'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_lock_open.png'), alt: ''
%h1= t 'devise.mailer.password_change.title' %h1= t 'devise.mailer.password_change.title'
%p.lead= t 'devise.mailer.password_change.explanation' %p.lead= t 'devise.mailer.password_change.explanation'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_email.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_email.png'), alt: ''
%h1= t 'devise.mailer.reconfirmation_instructions.title' %h1= t 'devise.mailer.reconfirmation_instructions.title'
%p.lead= t 'devise.mailer.reconfirmation_instructions.explanation' %p.lead= t 'devise.mailer.reconfirmation_instructions.explanation'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_lock_open.png'), alt: ''
%h1= t 'devise.mailer.reset_password_instructions.title' %h1= t 'devise.mailer.reset_password_instructions.title'
%p.lead= t 'devise.mailer.reset_password_instructions.explanation' %p.lead= t 'devise.mailer.reset_password_instructions.explanation'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_lock_open.png'), alt: ''
%h1= t 'user_mailer.suspicious_sign_in.title' %h1= t 'user_mailer.suspicious_sign_in.title'
%p= t 'user_mailer.suspicious_sign_in.explanation' %p= t 'user_mailer.suspicious_sign_in.explanation'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_lock_open.png'), alt: ''
%h1= t 'devise.mailer.two_factor_disabled.title' %h1= t 'devise.mailer.two_factor_disabled.title'
%p.lead= t 'devise.mailer.two_factor_disabled.explanation' %p.lead= t 'devise.mailer.two_factor_disabled.explanation'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_lock_open.png'), alt: ''
%h1= t 'devise.mailer.two_factor_enabled.title' %h1= t 'devise.mailer.two_factor_enabled.title'
%p.lead= t 'devise.mailer.two_factor_enabled.explanation' %p.lead= t 'devise.mailer.two_factor_enabled.explanation'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_lock_open.png'), alt: ''
%h1= t 'devise.mailer.two_factor_recovery_codes_changed.title' %h1= t 'devise.mailer.two_factor_recovery_codes_changed.title'
%p.lead= t 'devise.mailer.two_factor_recovery_codes_changed.explanation' %p.lead= t 'devise.mailer.two_factor_recovery_codes_changed.explanation'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_flag.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_flag.png'), alt: ''
%h1= t "user_mailer.warning.title.#{@warning.action}" %h1= t "user_mailer.warning.title.#{@warning.action}"

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_lock_open.png'), alt: ''
%h1= t 'devise.mailer.webauthn_credential.added.title' %h1= t 'devise.mailer.webauthn_credential.added.title'
%p.lead= "#{t 'devise.mailer.webauthn_credential.added.explanation' }:" %p.lead= "#{t 'devise.mailer.webauthn_credential.added.explanation' }:"

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_lock_open.png'), alt: ''
%h1= t 'devise.mailer.webauthn_credential.deleted.title' %h1= t 'devise.mailer.webauthn_credential.deleted.title'
%p.lead= "#{t 'devise.mailer.webauthn_credential.deleted.explanation' }:" %p.lead= "#{t 'devise.mailer.webauthn_credential.deleted.explanation' }:"

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_lock_open.png'), alt: ''
%h1= t 'devise.mailer.webauthn_disabled.title' %h1= t 'devise.mailer.webauthn_disabled.title'
%p.lead= t 'devise.mailer.webauthn_disabled.explanation' %p.lead= t 'devise.mailer.webauthn_disabled.explanation'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_lock_open.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_lock_open.png'), alt: ''
%h1= t 'devise.mailer.webauthn_enabled.title' %h1= t 'devise.mailer.webauthn_enabled.title'
%p.lead= t 'devise.mailer.webauthn_enabled.explanation' %p.lead= t 'devise.mailer.webauthn_enabled.explanation'

View File

@ -17,7 +17,7 @@
%tbody %tbody
%tr %tr
%td %td
= image_tag full_pack_url('media/images/mailer/icon_done.png'), alt: '' = image_tag full_pack_url('static/mailer/icon_done.png'), alt: ''
%h1= t 'user_mailer.welcome.title', name: @resource.account.username %h1= t 'user_mailer.welcome.title', name: @resource.account.username
%p.lead= t 'user_mailer.welcome.explanation' %p.lead= t 'user_mailer.welcome.explanation'

View File

@ -1,18 +1,14 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
ENV["NODE_ENV"] ||= "development"
require "pathname" require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath)
require "rubygems"
require "bundler/setup" require "bundler/setup"
require "webpacker" require "webpacker"
require "webpacker/webpack_runner" require "webpacker/webpack_runner"
ENV["RAILS_ENV"] ||= "development"
ENV["NODE_ENV"] ||= ENV["RAILS_ENV"]
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath)
APP_ROOT = File.expand_path("..", __dir__) APP_ROOT = File.expand_path("..", __dir__)
Dir.chdir(APP_ROOT) do Dir.chdir(APP_ROOT) do
Webpacker::WebpackRunner.run(ARGV) Webpacker::WebpackRunner.run(ARGV)

View File

@ -1,13 +1,12 @@
#!/usr/bin/env ruby #!/usr/bin/env ruby
ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" ENV["RAILS_ENV"] ||= "development"
ENV["NODE_ENV"] ||= "development" ENV["NODE_ENV"] ||= ENV["RAILS_ENV"]
require "pathname" require "pathname"
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
Pathname.new(__FILE__).realpath) Pathname.new(__FILE__).realpath)
require "rubygems"
require "bundler/setup" require "bundler/setup"
require "webpacker" require "webpacker"

View File

@ -1,17 +0,0 @@
#!/usr/bin/env ruby
APP_ROOT = File.expand_path('..', __dir__)
Dir.chdir(APP_ROOT) do
yarn = ENV["PATH"].split(File::PATH_SEPARATOR).
select { |dir| File.expand_path(dir) != __dir__ }.
product(["yarn", "yarn.cmd", "yarn.ps1"]).
map { |dir, file| File.expand_path(file, dir) }.
find { |file| File.executable?(file) }
if yarn
exec yarn, *ARGV
else
$stderr.puts "Yarn executable was not detected in the system."
$stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install"
exit 1
end
end

View File

@ -1,27 +0,0 @@
// Common configuration for webpacker loaded from config/webpacker.yml
const { resolve } = require('path');
const { env } = require('process');
const { load } = require('js-yaml');
const { readFileSync } = require('fs');
const configPath = resolve('config', 'webpacker.yml');
const settings = load(readFileSync(configPath), 'utf8')[env.RAILS_ENV || env.NODE_ENV];
const themePath = resolve('config', 'themes.yml');
const themes = load(readFileSync(themePath), 'utf8');
const output = {
path: resolve('public', settings.public_output_path),
publicPath: `/${settings.public_output_path}/`,
};
module.exports = {
settings,
themes,
env: {
NODE_ENV: env.NODE_ENV,
PUBLIC_OUTPUT_PATH: settings.public_output_path,
},
output,
};

View File

@ -1,61 +0,0 @@
// Note: You must restart bin/webpack-dev-server for changes to take effect
const { merge } = require('webpack-merge');
const sharedConfig = require('./shared');
const { settings, output } = require('./configuration');
const watchOptions = {};
if (process.env.VAGRANT) {
// If we are in Vagrant, we can't rely on inotify to update us with changed
// files, so we must poll instead. Here, we poll every second to see if
// anything has changed.
watchOptions.poll = 1000;
}
module.exports = merge(sharedConfig, {
mode: 'development',
cache: true,
devtool: 'cheap-module-eval-source-map',
stats: {
errorDetails: true,
},
output: {
pathinfo: true,
},
devServer: {
clientLogLevel: 'none',
compress: settings.dev_server.compress,
quiet: settings.dev_server.quiet,
disableHostCheck: settings.dev_server.disable_host_check,
host: settings.dev_server.host,
port: settings.dev_server.port,
https: settings.dev_server.https,
hot: settings.dev_server.hmr,
contentBase: output.path,
inline: settings.dev_server.inline,
useLocalIp: settings.dev_server.use_local_ip,
public: settings.dev_server.public,
publicPath: output.publicPath,
historyApiFallback: {
disableDotRule: true,
},
headers: settings.dev_server.headers,
overlay: settings.dev_server.overlay,
stats: {
entrypoints: false,
errorDetails: false,
modules: false,
moduleTrace: false,
},
watchOptions: Object.assign(
{},
settings.dev_server.watch_options,
watchOptions,
),
writeToDisk: filePath => /ocr/.test(filePath),
},
});

6
config/webpack/env.js Normal file
View File

@ -0,0 +1,6 @@
const { config, env } = require('shakapacker');
module.exports = {
NODE_ENV: env.nodeEnv,
PUBLIC_OUTPUT_PATH: config.public_output_path,
};

View File

@ -0,0 +1,91 @@
const { readFileSync } = require('fs');
const { load } = require('js-yaml');
const { basename, join, resolve } = require('path');
const extname = require('path-complete-extname');
const { config, merge, webpackConfig: originalBaseWebpackConfig } = require('shakapacker');
const webpack = require('webpack');
const WebpackAssetsManifest = require('webpack-assets-manifest');
const env = require('../env');
const nodeModulesRule = require('../rules/node_modules');
const tesseractRule = require('../rules/tesseract');
const localePackPaths = require('../generateLocalePacks');
const themePath = resolve('config', 'themes.yml');
const themes = load(readFileSync(themePath), 'utf8');
/**
* @param {import('webpack').WebpackPluginInstance | ((this: webpack.Compiler, compiler: webpack.Compiler) => void)} plugin
* @returns {boolean}
*/
function isAllowedPlugin(plugin) {
return !(plugin instanceof WebpackAssetsManifest || plugin instanceof webpack.EnvironmentPlugin);
}
/** @type {import('webpack').Configuration} */
const baseWebpackConfig = {
...originalBaseWebpackConfig,
optimization: {},
plugins: originalBaseWebpackConfig.plugins.filter(isAllowedPlugin),
};
/** @type {import('webpack').Configuration} */
const options = {
target: 'web',
entry: {
...localePackPaths.reduce((map, entry) => ({
...map,
[basename(entry, extname(entry, extname(entry)))]: resolve(entry),
}), {}),
...Object.keys(themes).reduce((themePaths, name) => ({
...themePaths,
[name]: resolve(join(config.source_path, themes[name])),
}), {}),
},
module: {
rules: [
nodeModulesRule,
tesseractRule,
],
},
optimization: {
chunkIds: 'total-size',
moduleIds: 'size',
runtimeChunk: {
name: 'common',
},
splitChunks: {
cacheGroups: {
default: false,
vendors: false,
common: {
name: 'common',
chunks: 'all',
minChunks: 2,
minSize: 0,
test: /^(?!.*[\\\/]node_modules[\\\/]react-intl[\\\/]).+$/,
},
},
},
},
plugins: [
new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
new WebpackAssetsManifest({
entrypoints: true,
entrypointsUseAssets: true,
integrity: true,
integrityHashes: ['sha256'],
output: config.manifestPath,
publicPath: true,
writeToDisk: true,
}),
new webpack.NormalModuleReplacementPlugin(
/^history\//, (resource) => {
// temporary fix for https://github.com/ReactTraining/react-router/issues/5576
// to reduce bundle size
resource.request = resource.request.replace(/^history/, 'history/es');
},
),
],
};
module.exports = merge({}, baseWebpackConfig, options);

View File

@ -0,0 +1,39 @@
const { env, merge } = require('shakapacker');
const markRule = require('../rules/mark');
const baseConfig = require('./base');
/** @type {import('webpack').Configuration} */
let developmentConfig = {
module: {
rules: [
markRule,
],
},
};
if (env.runningWebpackDevServer) {
developmentConfig = merge(developmentConfig, {
devServer: {
devMiddleware: {
writeToDisk: filePath => /ocr/.test(filePath),
},
},
});
}
if (process.env.VAGRANT) {
developmentConfig = merge(developmentConfig, {
devServer: {
static: {
watch: {
// If we are in Vagrant, we can't rely on inotify to update us with changed
// files, so we must poll instead. Here, we poll every second to see if
// anything has changed.
poll: 1_000,
},
},
},
});
}
module.exports = merge({}, baseConfig, developmentConfig);

View File

@ -1,39 +1,16 @@
// Note: You must restart bin/webpack-dev-server for changes to take effect
const { createHash } = require('crypto'); const { createHash } = require('crypto');
const { readFileSync } = require('fs'); const { readFileSync } = require('fs');
const { resolve } = require('path'); const { resolve } = require('path');
const { merge } = require('webpack-merge'); const { merge } = require('shakapacker');
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer'); const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
const TerserPlugin = require('terser-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const { InjectManifest } = require('workbox-webpack-plugin'); const { InjectManifest } = require('workbox-webpack-plugin');
const sharedConfig = require('./shared'); const baseConfig = require('./base');
const root = resolve(__dirname, '..', '..'); const root = resolve(__dirname, '..', '..', '..');
module.exports = merge(sharedConfig, {
mode: 'production',
devtool: 'source-map',
stats: 'normal',
bail: true,
optimization: {
minimize: true,
minimizer: [
new TerserPlugin({
cache: true,
parallel: true,
sourceMap: true,
}),
],
},
/** @type {import('webpack').Configuration} */
const productionConfig = {
plugins: [ plugins: [
new CompressionPlugin({
filename: '[path][base].gz[query]',
cache: true,
test: /\.(js|css|html|json|ico|svg|eot|otf|ttf|map)$/,
}),
new BundleAnalyzerPlugin({ // generates report.html new BundleAnalyzerPlugin({ // generates report.html
analyzerMode: 'static', analyzerMode: 'static',
openAnalyzer: false, openAnalyzer: false,
@ -63,4 +40,6 @@ module.exports = merge(sharedConfig, {
swSrc: resolve(root, 'app', 'javascript', 'mastodon', 'service_worker', 'entry.js'), swSrc: resolve(root, 'app', 'javascript', 'mastodon', 'service_worker', 'entry.js'),
}), }),
], ],
}); };
module.exports = merge({}, baseConfig, productionConfig);

View File

@ -0,0 +1,9 @@
const { merge } = require('shakapacker');
const baseConfig = require('./base');
/** @type {import('webpack').Configuration} */
const testConfig = {
mode: 'development',
};
module.exports = merge({}, baseConfig, testConfig);

View File

@ -1,21 +0,0 @@
const { join, resolve } = require('path');
const { env, settings } = require('../configuration');
module.exports = {
test: /\.(js|jsx|mjs)$/,
include: [
settings.source_path,
...settings.resolved_paths,
].map(p => resolve(p)),
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
cacheDirectory: join(settings.cache_path, 'babel-loader'),
cacheCompression: env.NODE_ENV === 'production',
compact: env.NODE_ENV === 'production',
},
},
],
};

View File

@ -1,28 +0,0 @@
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
test: /\.s?css$/i,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
sourceMap: true,
importLoaders: 2,
},
},
{
loader: 'postcss-loader',
options: {
sourceMap: true,
},
},
{
loader: 'sass-loader',
options: {
implementation: require('sass'),
sourceMap: true,
},
},
],
};

View File

@ -1,20 +0,0 @@
const { join } = require('path');
const { settings } = require('../configuration');
module.exports = {
test: new RegExp(`(${settings.static_assets_extensions.join('|')})$`, 'i'),
use: [
{
loader: 'file-loader',
options: {
name(file) {
if (file.includes(settings.source_path)) {
return 'media/[path][name]-[hash].[ext]';
}
return 'media/[folder]/[name]-[hash:8].[ext]';
},
context: join(settings.source_path),
},
},
],
};

View File

@ -1,16 +0,0 @@
const babel = require('./babel');
const css = require('./css');
const file = require('./file');
const tesseract = require('./tesseract');
const nodeModules = require('./node_modules');
// Webpack loaders are processed in reverse order
// https://webpack.js.org/concepts/loaders/#loader-features
// Lastly, process static files using file loader
module.exports = {
file,
tesseract,
css,
nodeModules,
babel,
};

View File

@ -1,8 +1,4 @@
if (process.env.NODE_ENV === 'production') {
module.exports = {};
} else {
module.exports = { module.exports = {
test: /\.js$/, test: /\.js$/,
loader: 'mark-loader', loader: 'mark-loader',
}; };
}

View File

@ -1,5 +1,5 @@
const { join } = require('path'); const { join } = require('path');
const { settings, env } = require('../configuration'); const { config, env } = require('shakapacker');
module.exports = { module.exports = {
test: /\.(js|mjs)$/, test: /\.(js|mjs)$/,
@ -16,8 +16,8 @@ module.exports = {
plugins: [ plugins: [
'transform-react-remove-prop-types', 'transform-react-remove-prop-types',
], ],
cacheDirectory: join(settings.cache_path, 'babel-loader-node-modules'), cacheDirectory: join(config.cache_path, 'babel-loader-node-modules'),
cacheCompression: env.NODE_ENV === 'production', cacheCompression: env.isProduction,
compact: false, compact: false,
sourceMaps: false, sourceMaps: false,
}, },

View File

@ -1,14 +1,12 @@
module.exports = { module.exports = {
generator: {
filename: 'ocr/[name]-[hash][ext]',
},
test: [ test: [
/tesseract\.js\/dist\/worker\.min\.js$/, /tesseract\.js\/dist\/worker\.min\.js$/,
/tesseract\.js\/dist\/worker\.min\.js.map$/, /tesseract\.js\/dist\/worker\.min\.js.map$/,
/tesseract\.js-core\/tesseract-core\.wasm$/, /tesseract\.js-core\/tesseract-core\.wasm$/,
/tesseract\.js-core\/tesseract-core\.wasm.js$/, /tesseract\.js-core\/tesseract-core\.wasm.js$/,
], ],
use: { type: 'asset/resource',
loader: 'file-loader',
options: {
name: 'ocr/[name]-[hash].[ext]',
},
},
}; };

View File

@ -1,108 +0,0 @@
// Note: You must restart bin/webpack-dev-server for changes to take effect
const webpack = require('webpack');
const { basename, dirname, join, relative, resolve } = require('path');
const { sync } = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const AssetsManifestPlugin = require('webpack-assets-manifest');
const extname = require('path-complete-extname');
const { env, settings, themes, output } = require('./configuration');
const rules = require('./rules');
const localePackPaths = require('./generateLocalePacks');
const extensionGlob = `**/*{${settings.extensions.join(',')}}*`;
const entryPath = join(settings.source_path, settings.source_entry_path);
const packPaths = sync(join(entryPath, extensionGlob));
module.exports = {
entry: Object.assign(
packPaths.reduce((map, entry) => {
const localMap = map;
const namespace = relative(join(entryPath), dirname(entry));
localMap[join(namespace, basename(entry, extname(entry)))] = resolve(entry);
return localMap;
}, {}),
localePackPaths.reduce((map, entry) => {
const localMap = map;
localMap[basename(entry, extname(entry, extname(entry)))] = resolve(entry);
return localMap;
}, {}),
Object.keys(themes).reduce((themePaths, name) => {
themePaths[name] = resolve(join(settings.source_path, themes[name]));
return themePaths;
}, {}),
),
output: {
filename: 'js/[name]-[chunkhash].js',
chunkFilename: 'js/[name]-[chunkhash].chunk.js',
hotUpdateChunkFilename: 'js/[id]-[hash].hot-update.js',
hashFunction: 'sha256',
path: output.path,
publicPath: output.publicPath,
},
optimization: {
runtimeChunk: {
name: 'common',
},
splitChunks: {
cacheGroups: {
default: false,
vendors: false,
common: {
name: 'common',
chunks: 'all',
minChunks: 2,
minSize: 0,
test: /^(?!.*[\\\/]node_modules[\\\/]react-intl[\\\/]).+$/,
},
},
},
occurrenceOrder: true,
},
module: {
rules: Object.keys(rules).map(key => rules[key]),
},
plugins: [
new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
new webpack.NormalModuleReplacementPlugin(
/^history\//, (resource) => {
// temporary fix for https://github.com/ReactTraining/react-router/issues/5576
// to reduce bundle size
resource.request = resource.request.replace(/^history/, 'history/es');
},
),
new MiniCssExtractPlugin({
filename: 'css/[name]-[contenthash:8].css',
chunkFilename: 'css/[name]-[contenthash:8].chunk.css',
}),
new AssetsManifestPlugin({
integrity: true,
integrityHashes: ['sha256'],
entrypoints: true,
writeToDisk: true,
publicPath: true,
}),
],
resolve: {
extensions: settings.extensions,
modules: [
resolve(settings.source_path),
'node_modules',
],
},
resolveLoader: {
modules: ['node_modules'],
},
node: {
// Called by http-link-header in an API we never use, increases
// bundle size unnecessarily
Buffer: false,
},
};

View File

@ -1,8 +0,0 @@
// Note: You must restart bin/webpack-dev-server for changes to take effect
const { merge } = require('webpack-merge');
const sharedConfig = require('./shared');
module.exports = merge(sharedConfig, {
mode: 'development',
});

View File

@ -0,0 +1,14 @@
const { existsSync } = require('fs');
const { resolve } = require('path');
const { env } = require('shakapacker');
const baseConfig = require('./environments/base');
function getWebpackConfig() {
const { nodeEnv } = env;
const path = resolve(__dirname, 'environments', `${nodeEnv}.js`);
const enviromentConfig = existsSync(path) ? require(path) : baseConfig;
return enviromentConfig;
}
module.exports = getWebpackConfig();

View File

@ -1,55 +1,31 @@
# Note: You must restart bin/webpack-dev-server for changes to take effect # Note: You must restart bin/webpacker-dev-server for changes to take effect
default: &default default: &default
source_path: app/javascript source_path: app/javascript
source_entry_path: packs source_entry_path: /
public_root_path: public public_root_path: public
public_output_path: packs public_output_path: packs
cache_path: tmp/cache/webpacker cache_path: tmp/webpacker
check_yarn_integrity: false webpack_compile_output: true
webpack_compile_output: false
# Location for manifest.json, defaults to {public_output_path}/manifest.json if unset
# manifest_path: public/packs/manifest.json
# Additional paths webpack should look up modules # Additional paths webpack should look up modules
# ['app/assets', 'engine/foo/app/assets'] # ['app/assets', 'engine/foo/app/assets']
resolved_paths: [] additional_paths: []
# Reload manifest.json on all requests so we reload latest compiled packs # Reload manifest.json on all requests so we reload latest compiled packs
cache_manifest: false cache_manifest: false
# Extract and emit a css file # Select loader to use, available options are 'babel' (default), 'swc' or 'esbuild'
extract_css: true webpack_loader: 'babel'
static_assets_extensions: # Set to true to enable check for matching versions of shakapacker gem and NPM package - will raise an error if there is a mismatch or wildcard versioning is used
- .jpg ensure_consistent_versioning: false
- .jpeg
- .png
- .tiff
- .ico
- .svg
- .eot
- .otf
- .ttf
- .woff
- .woff2
extensions:
- .mjs
- .js
- .sass
- .scss
- .css
- .module.sass
- .module.scss
- .module.css
- .png
- .svg
- .gif
- .jpeg
- .jpg
development: development:
<<: *default <<: *default
compile: true compile: true
# Reference: https://webpack.js.org/configuration/dev-server/ # Reference: https://webpack.js.org/configuration/dev-server/
@ -57,23 +33,39 @@ development:
https: false https: false
host: localhost host: localhost
port: 3035 port: 3035
public: localhost:3035 # Hot Module Replacement updates modules while the application is running without a full reload
hmr: false hmr: false
# Inline should be set to true if using HMR # If HMR is on, CSS will by inlined by delivering it as part of the script payload via style-loader. Be sure
inline: true # that you add style-loader to your project dependencies.
#
# If you want to instead deliver CSS via <link> with the mini-extract-css-plugin, set inline_css to false.
# In that case, style-loader is not needed as a dependency.
#
# mini-extract-css-plugin is a required dependency in both cases.
inline_css: false
# Defaults to the inverse of hmr. Uncomment to manually set this.
# live_reload: true
client:
# Should we show a full-screen overlay in the browser when there are compiler errors or warnings?
overlay: true overlay: true
# May also be a string
# webSocketURL:
# hostname: "0.0.0.0"
# pathname: "/ws"
# port: 8080
# Should we use gzip compression?
compress: true compress: true
disable_host_check: true # Note that apps that do not check the host are vulnerable to DNS rebinding attacks
use_local_ip: false allowed_hosts: "all"
quiet: false pretty: true
headers: headers:
'Access-Control-Allow-Origin': '*' 'Access-Control-Allow-Origin': '*'
watch_options: static:
watch:
ignored: '**/node_modules/**' ignored: '**/node_modules/**'
test: test:
<<: *default <<: *default
# CircleCI precompiles packs prior to running the tests. # CircleCI precompiles packs prior to running the tests.
# Also avoids race conditions in parallel_tests. # Also avoids race conditions in parallel_tests.
compile: false compile: false

View File

@ -6,8 +6,8 @@
}, },
"scripts": { "scripts": {
"postversion": "git push --tags", "postversion": "git push --tags",
"build:development": "cross-env RAILS_ENV=development NODE_ENV=development ./bin/webpack", "build:development": "cross-env RAILS_ENV=development NODE_ENV=development ./bin/webpacker",
"build:production": "cross-env RAILS_ENV=production NODE_ENV=production ./bin/webpack", "build:production": "cross-env RAILS_ENV=production NODE_ENV=production ./bin/webpacker",
"manage:translations": "node ./config/webpack/translationRunner.js", "manage:translations": "node ./config/webpack/translationRunner.js",
"start": "node ./streaming/index.js", "start": "node ./streaming/index.js",
"test": "${npm_execpath} run test:lint:js && ${npm_execpath} run test:jest", "test": "${npm_execpath} run test:lint:js && ${npm_execpath} run test:jest",
@ -33,10 +33,10 @@
"@babel/runtime": "^7.19.0", "@babel/runtime": "^7.19.0",
"@gamestdio/websocket": "^0.3.2", "@gamestdio/websocket": "^0.3.2",
"@github/webauthn-json": "^0.5.7", "@github/webauthn-json": "^0.5.7",
"@rails/ujs": "^6.1.6", "@rails/ujs": "^6.1.7",
"array-includes": "^3.1.5", "array-includes": "^3.1.5",
"arrow-key-navigation": "^1.2.0", "arrow-key-navigation": "^1.2.0",
"autoprefixer": "^9.8.8", "autoprefixer": "^10.4.8",
"axios": "^0.27.2", "axios": "^0.27.2",
"babel-loader": "^8.2.5", "babel-loader": "^8.2.5",
"babel-plugin-lodash": "^3.3.4", "babel-plugin-lodash": "^3.3.4",
@ -47,10 +47,10 @@
"classnames": "^2.3.1", "classnames": "^2.3.1",
"cocoon-js-vanilla": "^1.3.0", "cocoon-js-vanilla": "^1.3.0",
"color-blend": "^3.0.1", "color-blend": "^3.0.1",
"compression-webpack-plugin": "^6.1.1", "compression-webpack-plugin": "^10.0.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"css-loader": "^5.2.7", "css-loader": "^6.7.1",
"cssnano": "^4.1.11", "css-minimizer-webpack-plugin": "^3.4.1",
"detect-passive-events": "^2.0.3", "detect-passive-events": "^2.0.3",
"dotenv": "^16.0.2", "dotenv": "^16.0.2",
"emoji-mart": "npm:emoji-mart-lazyload", "emoji-mart": "npm:emoji-mart-lazyload",
@ -58,14 +58,12 @@
"escape-html": "^1.0.3", "escape-html": "^1.0.3",
"exif-js": "^2.3.0", "exif-js": "^2.3.0",
"express": "^4.18.1", "express": "^4.18.1",
"file-loader": "^6.2.0",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"fuzzysort": "^1.9.0", "fuzzysort": "^1.9.0",
"glob": "^8.0.3", "glob": "^8.0.3",
"history": "^4.10.1", "history": "^4.10.1",
"http-link-header": "^1.0.5", "http-link-header": "^1.0.5",
"immutable": "^4.1.0", "immutable": "^4.1.0",
"imports-loader": "^1.2.0",
"intersection-observer": "^0.12.2", "intersection-observer": "^0.12.2",
"intl": "^1.2.5", "intl": "^1.2.5",
"intl-messageformat": "^2.2.0", "intl-messageformat": "^2.2.0",
@ -76,7 +74,7 @@
"lodash": "^4.17.21", "lodash": "^4.17.21",
"mark-loader": "^0.1.6", "mark-loader": "^0.1.6",
"marky": "^1.2.5", "marky": "^1.2.5",
"mini-css-extract-plugin": "^1.6.2", "mini-css-extract-plugin": "^2.6.1",
"mkdirp": "^1.0.4", "mkdirp": "^1.0.4",
"npmlog": "^6.0.2", "npmlog": "^6.0.2",
"object-assign": "^4.1.1", "object-assign": "^4.1.1",
@ -85,7 +83,7 @@
"path-complete-extname": "^1.0.0", "path-complete-extname": "^1.0.0",
"pg": "^8.5.0", "pg": "^8.5.0",
"postcss": "^8.4.16", "postcss": "^8.4.16",
"postcss-loader": "^3.0.0", "postcss-loader": "^6.2.1",
"postcss-object-fit-images": "^1.1.2", "postcss-object-fit-images": "^1.1.2",
"promise.prototype.finally": "^3.1.3", "promise.prototype.finally": "^3.1.3",
"prop-types": "^15.8.1", "prop-types": "^15.8.1",
@ -118,21 +116,21 @@
"requestidlecallback": "^0.3.0", "requestidlecallback": "^0.3.0",
"reselect": "^4.1.6", "reselect": "^4.1.6",
"rimraf": "^3.0.2", "rimraf": "^3.0.2",
"sass": "^1.54.8", "sass": "^1.54.9",
"sass-loader": "^10.2.0", "sass-loader": "^12.6.0",
"shakapacker": "6.5.2",
"stacktrace-js": "^2.0.2", "stacktrace-js": "^2.0.2",
"stringz": "^2.1.0", "stringz": "^2.1.0",
"substring-trie": "^1.0.2", "substring-trie": "^1.0.2",
"terser-webpack-plugin": "^4.2.3",
"tesseract.js": "^2.1.1", "tesseract.js": "^2.1.1",
"throng": "^4.0.0", "throng": "^4.0.0",
"tiny-queue": "^0.2.1", "tiny-queue": "^0.2.1",
"twitter-text": "3.1.0", "twitter-text": "3.1.0",
"uuid": "^8.3.1", "uuid": "^8.3.1",
"webpack": "^4.46.0", "webpack": "^5.74.0",
"webpack-assets-manifest": "^4.0.6", "webpack-assets-manifest": "^5.1.0",
"webpack-bundle-analyzer": "^4.6.1", "webpack-bundle-analyzer": "^4.6.1",
"webpack-cli": "^3.3.12", "webpack-cli": "^4.10.0",
"webpack-merge": "^5.8.0", "webpack-merge": "^5.8.0",
"wicg-inert": "^3.1.2", "wicg-inert": "^3.1.2",
"workbox-expiration": "^6.5.4", "workbox-expiration": "^6.5.4",
@ -162,7 +160,7 @@
"react-test-renderer": "^16.14.0", "react-test-renderer": "^16.14.0",
"stylelint": "^14.11.0", "stylelint": "^14.11.0",
"stylelint-config-standard-scss": "^5.0.0", "stylelint-config-standard-scss": "^5.0.0",
"webpack-dev-server": "^3.11.3", "webpack-dev-server": "^4.11.0",
"yargs": "^17.5.1" "yargs": "^17.5.1"
}, },
"resolutions": { "resolutions": {

View File

@ -1,7 +1,6 @@
module.exports = ({ env }) => ({ module.exports = () => ({
plugins: { plugins: {
autoprefixer: {}, autoprefixer: {},
'postcss-object-fit-images': {}, 'postcss-object-fit-images': {},
cssnano: env === 'production' ? {} : false,
}, },
}); });

4820
yarn.lock

File diff suppressed because it is too large Load Diff