add localisation via ttag
This commit is contained in:
parent
087319be96
commit
0c5ab8bf97
13
i18n/de.po
Normal file
13
i18n/de.po
Normal file
|
@ -0,0 +1,13 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Plural-Forms: nplurals = 2; plural = (n != 1);\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/components/ForgotPasswordModal.jsx:20
|
||||
#: src/components/RegisterModal.jsx:21
|
||||
#: src/components/UserAreaModal.jsx:128
|
||||
msgid "Consider joining us on Guilded:"
|
||||
msgstr "Sprich zu uns und anderen Spielern auf guilded:"
|
13
i18n/es.po
Normal file
13
i18n/es.po
Normal file
|
@ -0,0 +1,13 @@
|
|||
msgid ""
|
||||
msgstr ""
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Plural-Forms: nplurals = 2; plural = (n != 1);\n"
|
||||
"Language: de\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/components/ForgotPasswordModal.jsx:20
|
||||
#: src/components/RegisterModal.jsx:21
|
||||
#: src/components/UserAreaModal.jsx:128
|
||||
msgid "Consider joining us on Guilded:"
|
||||
msgstr "Sprich zu uns und anderen Spielern auf guilded:"
|
919
package-lock.json
generated
919
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
|
@ -77,6 +77,7 @@
|
|||
"sweetalert2": "^10.12.1",
|
||||
"three": "^0.123.0",
|
||||
"three-trackballcontrols": "^0.9.0",
|
||||
"ttag": "^1.7.24",
|
||||
"url-search-params-polyfill": "^8.1.0",
|
||||
"winston": "^3.3.3",
|
||||
"winston-daily-rotate-file": "^4.5.0",
|
||||
|
@ -115,6 +116,7 @@
|
|||
"babel-loader": "^8.2.2",
|
||||
"babel-plugin-transform-react-pure-class-to-function": "^1.0.1",
|
||||
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
|
||||
"babel-plugin-ttag": "^1.7.30",
|
||||
"clean-css": "^4.2.3",
|
||||
"css-loader": "^5.0.1",
|
||||
"eslint": "^7.15.0",
|
||||
|
@ -134,6 +136,7 @@
|
|||
"react-svg-loader": "^3.0.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"style-loader": "^2.0.0",
|
||||
"ttag-cli": "^1.9.1",
|
||||
"webpack": "^5.10.0",
|
||||
"webpack-bundle-analyzer": "^4.2.0",
|
||||
"webpack-cli": "^4.2.0",
|
||||
|
|
|
@ -7,10 +7,14 @@
|
|||
* LICENSE.txt file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import webpack from 'webpack';
|
||||
import webpackConfigWeb from '../webpack.config.web.babel';
|
||||
import webpackConfigClient from '../webpack.config.client.babel';
|
||||
import { buildWebpackClientConfig } from '../webpack.config.client.babel';
|
||||
|
||||
const wpStats = {
|
||||
colors: true,
|
||||
|
@ -22,12 +26,12 @@ const wpStats = {
|
|||
chunkModules: false,
|
||||
cached: false,
|
||||
cachedAssets: false,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates application bundles from the source files.
|
||||
*/
|
||||
function bundle() {
|
||||
async function bundle() {
|
||||
try {
|
||||
/* fix image-q imports here
|
||||
* Pretty dirty, but we did write an issue and they might
|
||||
|
@ -36,12 +40,21 @@ function bundle() {
|
|||
console.log('Patching image-q set-immediate import');
|
||||
const regex = /core-js\/fn\/set-immediate/g;
|
||||
const files = [
|
||||
'./node_modules/image-q/dist/esm/basicAPI.js',
|
||||
'./node_modules/image-q/dist/esm/helper.js',
|
||||
path.resolve(
|
||||
'..', 'node_modules',
|
||||
'image-q', 'dist', 'esm', 'basicAPI.js',
|
||||
),
|
||||
path.resolve(
|
||||
'..', 'node_modules',
|
||||
'image-q', 'dist', 'esm', 'helper.js',
|
||||
),
|
||||
];
|
||||
files.forEach((file) => {
|
||||
let fileContent = fs.readFileSync(file, 'utf8');
|
||||
fileContent = fileContent.replace(regex, 'core-js/features/set-immediate');
|
||||
fileContent = fileContent.replace(
|
||||
regex,
|
||||
'core-js/features/set-immediate',
|
||||
);
|
||||
fs.writeFileSync(file, fileContent);
|
||||
});
|
||||
console.log('Patching image-q done');
|
||||
|
@ -50,8 +63,24 @@ function bundle() {
|
|||
}
|
||||
console.log('Bundle with webpack....');
|
||||
|
||||
let webpackConfig = [
|
||||
webpackConfigWeb,
|
||||
buildWebpackClientConfig(false, false, 'default'),
|
||||
]
|
||||
|
||||
/*
|
||||
* add other language configs
|
||||
*/
|
||||
const langDir = path.resolve(__dirname, '..', 'i18n');
|
||||
const langs = fs.readdirSync(langDir)
|
||||
.filter((e) => e.endsWith('.po'))
|
||||
.map((l) => l.slice(0, -3));
|
||||
webpackConfig = webpackConfig.concat(
|
||||
langs.map((l) => buildWebpackClientConfig(false, false, l)),
|
||||
);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
webpack([webpackConfigWeb, webpackConfigClient]).run((err, stats) => {
|
||||
webpack(webpackConfig).run((err, stats) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
import rimraf from 'rimraf';
|
||||
import path from 'path';
|
||||
|
||||
const builddir = path.resolve(__dirname, '../build');
|
||||
const builddir = path.resolve(__dirname, '..', 'build');
|
||||
|
||||
|
||||
function clean() {
|
||||
|
|
|
@ -9,10 +9,10 @@ import path from 'path';
|
|||
import glob from 'glob';
|
||||
import mkdirp from 'mkdirp';
|
||||
|
||||
const builddir = path.resolve(__dirname, '../build');
|
||||
const deploydir = path.resolve(__dirname, '../deployment');
|
||||
const publicdir = path.resolve(__dirname, '../public');
|
||||
const srcdir = path.resolve(__dirname, '../src');
|
||||
const builddir = path.resolve(__dirname, '..', 'build');
|
||||
const deploydir = path.resolve(__dirname, '..', 'deployment');
|
||||
const publicdir = path.resolve(__dirname, '..', 'public');
|
||||
const srcdir = path.resolve(__dirname, '..', 'src');
|
||||
|
||||
/*
|
||||
* following functions are copied from
|
||||
|
|
|
@ -9,10 +9,10 @@ import CleanCSS from 'clean-css';
|
|||
import crypto from 'crypto';
|
||||
|
||||
const rootdir = path.resolve(__dirname, '..');
|
||||
const assetdir = path.resolve(__dirname, '../build/public/assets');
|
||||
const builddir = path.resolve(__dirname, '../build');
|
||||
const assetdir = path.resolve(__dirname, '..', 'build', 'public', 'assets');
|
||||
const builddir = path.resolve(__dirname, '..', 'build');
|
||||
|
||||
const FOLDER = path.resolve(__dirname, '../src/styles');
|
||||
const FOLDER = path.resolve(__dirname, '..', 'src', 'styles');
|
||||
const FILES = [
|
||||
'default.css',
|
||||
'dark.css',
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { t } from 'ttag';
|
||||
|
||||
import { showUserAreaModal } from '../actions';
|
||||
import NewPasswordForm from './NewPasswordForm';
|
||||
|
@ -16,7 +17,7 @@ const ForgotPasswordModal = ({ login }) => (
|
|||
</p><br />
|
||||
<p style={{ textAlign: 'center' }}>
|
||||
<NewPasswordForm back={login} />
|
||||
<p>Consider joining us on Guilded:
|
||||
<p>{t`Consider joining us on Guilded:`}
|
||||
<a href="./guilded" target="_blank">pixelplanet.fun/guilded</a>
|
||||
</p>
|
||||
</p>
|
||||
|
|
|
@ -29,13 +29,23 @@ const styles = [{
|
|||
}];
|
||||
|
||||
const title = 'PixelPlanet.fun 3DGlobe';
|
||||
const description = '3D globe of our canvas';
|
||||
const scripts = [
|
||||
ASSET_SERVER + assets.three.js,
|
||||
ASSET_SERVER + assets.globe.js,
|
||||
];
|
||||
const description = 'pixelplanet globe';
|
||||
const defaultScripts = assets.globe.js.map(
|
||||
(s) => ASSET_SERVER + s,
|
||||
);
|
||||
const body = <Globe />;
|
||||
const globeHtml = `<!doctype html>${ReactDOM.renderToStaticMarkup(
|
||||
|
||||
/*
|
||||
* generates string with html of globe page
|
||||
* @param lang language code
|
||||
* @return html of mainpage
|
||||
*/
|
||||
function generateGlobePage(lang: string): string {
|
||||
const scripts = (assets[`globe-${lang}`])
|
||||
? assets[`globe-${lang}`].js.map((s) => ASSET_SERVER + s)
|
||||
: defaultScripts;
|
||||
|
||||
const html = ReactDOM.renderToStaticMarkup(
|
||||
<Html
|
||||
title={title}
|
||||
description={description}
|
||||
|
@ -43,6 +53,9 @@ const globeHtml = `<!doctype html>${ReactDOM.renderToStaticMarkup(
|
|||
body={body}
|
||||
styles={styles}
|
||||
/>,
|
||||
)}`;
|
||||
);
|
||||
|
||||
export default globeHtml;
|
||||
return `<!doctype html>${html}`;
|
||||
}
|
||||
|
||||
export default generateGlobePage;
|
||||
|
|
|
@ -22,10 +22,9 @@ let code = `window.assetserver="${ASSET_SERVER}";window.availableStyles=JSON.par
|
|||
if (BACKUP_URL) {
|
||||
code += `window.backupurl="${BACKUP_URL}";`;
|
||||
}
|
||||
const scripts = [
|
||||
ASSET_SERVER + assets.vendor.js,
|
||||
ASSET_SERVER + assets.client.js,
|
||||
];
|
||||
const defaultScripts = assets.client.js.map(
|
||||
(s) => ASSET_SERVER + s,
|
||||
);
|
||||
const css = [
|
||||
{
|
||||
id: 'globcss',
|
||||
|
@ -43,6 +42,9 @@ const css = [
|
|||
*/
|
||||
function generateMainPage(countryCoords: Cell, lang: string): string {
|
||||
const [x, y] = countryCoords;
|
||||
const scripts = (assets[`client-${lang}`])
|
||||
? assets[`client-${lang}`].js.map((s) => ASSET_SERVER + s)
|
||||
: defaultScripts;
|
||||
// eslint-disable-next-line
|
||||
const html = ReactDOM.renderToStaticMarkup(
|
||||
<Html
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { t } from 'ttag';
|
||||
|
||||
import { showUserAreaModal } from '../actions';
|
||||
|
||||
|
@ -17,7 +18,7 @@ const RegisterModal = ({ login }) => (
|
|||
<p className="modaltext">Register new account here</p><br />
|
||||
<p style={{ textAlign: 'center' }}>
|
||||
<SignUpForm back={login} />
|
||||
<p>Consider joining us on Guilded:
|
||||
<p>{t`Consider joining us on Guilded:`}
|
||||
<a href="./guilded" target="_blank">pixelplanet.fun/guilded</a>
|
||||
</p>
|
||||
</p>
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import React, { Suspense } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { t } from 'ttag';
|
||||
|
||||
import type { State } from '../reducers';
|
||||
|
||||
|
@ -124,7 +125,7 @@ const UserAreaModal = ({
|
|||
)}
|
||||
</Tabs>
|
||||
)}
|
||||
<p>Consider joining us on Guilded:
|
||||
<p>{t`Consider joining us on Guilded:`}
|
||||
<a href="./guilded" target="_blank">pixelplanet.fun/guilded</a>
|
||||
</p>
|
||||
</p>
|
||||
|
|
13
src/web.js
13
src/web.js
|
@ -26,7 +26,7 @@ import {
|
|||
admintools,
|
||||
resetPassword,
|
||||
} from './routes';
|
||||
import globeHtml from './components/Globe';
|
||||
import generateGlobePage from './components/Globe';
|
||||
import generateMainPage from './components/Main';
|
||||
|
||||
import { SECOND, MONTH } from './core/constants';
|
||||
|
@ -142,7 +142,7 @@ app.use('/reset_password', resetPassword);
|
|||
// 3D Globe (react generated)
|
||||
// -----------------------------------------------------------------------------
|
||||
const globeEtag = etag(
|
||||
`${assets.globe.js}`,
|
||||
assets.globe.js.join('_'),
|
||||
{ weak: true },
|
||||
);
|
||||
app.get('/globe', async (req, res) => {
|
||||
|
@ -157,7 +157,10 @@ app.get('/globe', async (req, res) => {
|
|||
return;
|
||||
}
|
||||
|
||||
res.status(200).send(globeHtml);
|
||||
const language = req.headers['accept-language'];
|
||||
const lang = (language) ? languageFromLocalisation(language) : 'en';
|
||||
|
||||
res.status(200).send(generateGlobePage(lang));
|
||||
});
|
||||
|
||||
|
||||
|
@ -165,7 +168,7 @@ app.get('/globe', async (req, res) => {
|
|||
// Main Page (react generated)
|
||||
// -----------------------------------------------------------------------------
|
||||
const indexEtag = etag(
|
||||
`${assets.vendor.js},${assets.client.js}`,
|
||||
assets.client.js.join('_'),
|
||||
{ weak: true },
|
||||
);
|
||||
|
||||
|
@ -183,7 +186,7 @@ app.get('/', async (req, res) => {
|
|||
|
||||
// get start coordinates based on cloudflare header country
|
||||
const country = req.headers['cf-ipcountry'];
|
||||
let language = req.headers['accept-language'];
|
||||
const language = req.headers['accept-language'];
|
||||
|
||||
const lang = (language) ? languageFromLocalisation(language) : 'en';
|
||||
const countryCoords = (country) ? ccToCoords(country) : [0, 0];
|
||||
|
|
|
@ -8,11 +8,24 @@ import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
|
|||
|
||||
import pkg from './package.json';
|
||||
|
||||
const isDebug = process.argv.includes('--debug');
|
||||
const VERBOSE = false;
|
||||
const isAnalyze = process.argv.includes('--analyze')
|
||||
|| process.argv.includes('--analyse');
|
||||
/*
|
||||
* Emit a file with assets paths
|
||||
*/
|
||||
const assetPlugin = new AssetsPlugin({
|
||||
path: path.resolve(__dirname, 'build'),
|
||||
filename: 'assets.json',
|
||||
entrypoints: true,
|
||||
prettyPrint: true,
|
||||
});
|
||||
|
||||
export function buildWebpackClientConfig(development, analyze, locale) {
|
||||
const ttag = {
|
||||
resolve: {
|
||||
translations: (locale !== 'default')
|
||||
? path.resolve(__dirname, 'i18n', `${locale}.po`)
|
||||
: locale,
|
||||
},
|
||||
};
|
||||
|
||||
const babelPlugins = [
|
||||
'@babel/transform-flow-strip-types',
|
||||
|
@ -28,31 +41,37 @@ const babelPlugins = [
|
|||
'@babel/transform-react-inline-elements',
|
||||
'transform-react-remove-prop-types',
|
||||
'transform-react-pure-class-to-function',
|
||||
['ttag', ttag],
|
||||
];
|
||||
|
||||
|
||||
export default {
|
||||
return {
|
||||
name: 'client',
|
||||
target: 'web',
|
||||
|
||||
context: __dirname,
|
||||
mode: (isDebug) ? 'development' : 'production',
|
||||
mode: (development) ? 'development' : 'production',
|
||||
devtool: 'source-map',
|
||||
|
||||
entry: {
|
||||
client: ['./src/client.js'],
|
||||
globe: ['./src/globe.js'],
|
||||
[(locale !== 'default') ? `client-${locale}` : 'client']:
|
||||
['./src/client.js'],
|
||||
[(locale !== 'default') ? `globe-${locale}` : 'globe']:
|
||||
['./src/globe.js'],
|
||||
},
|
||||
|
||||
output: {
|
||||
path: path.resolve(__dirname, './build/public/assets'),
|
||||
path: path.resolve(__dirname, 'build', 'public', 'assets'),
|
||||
publicPath: '/assets/',
|
||||
pathinfo: VERBOSE,
|
||||
filename: isDebug ? '[name].js' : '[name].[chunkhash:8].js',
|
||||
chunkFilename: isDebug ? '[name].chunk.js' : '[name].[chunkhash:8].js',
|
||||
filename: '[name].[chunkhash:8].js',
|
||||
chunkFilename: (locale !== 'default')
|
||||
? `[name]-${locale}.[chunkhash:8].js`
|
||||
: '[name].[chunkhash:8].js',
|
||||
},
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
ttag: 'ttag/dist/mock',
|
||||
},
|
||||
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
|
||||
},
|
||||
|
||||
|
@ -86,10 +105,10 @@ export default {
|
|||
test: /\.(js|jsx|ts|tsx)$/,
|
||||
loader: 'babel-loader',
|
||||
include: [
|
||||
path.resolve(__dirname, './src'),
|
||||
path.resolve(__dirname, 'src'),
|
||||
],
|
||||
options: {
|
||||
cacheDirectory: isDebug,
|
||||
cacheDirectory: development,
|
||||
babelrc: false,
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
|
@ -115,7 +134,7 @@ export default {
|
|||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
sourceMap: isDebug,
|
||||
sourceMap: development,
|
||||
modules: false,
|
||||
},
|
||||
},
|
||||
|
@ -128,21 +147,15 @@ export default {
|
|||
// Define free variables
|
||||
// https://webpack.github.io/docs/list-of-plugins.html#defineplugin
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': isDebug ? '"development"' : '"production"',
|
||||
'process.env.NODE_ENV': development ? '"development"' : '"production"',
|
||||
'process.env.BROWSER': true,
|
||||
}),
|
||||
|
||||
// Emit a file with assets paths
|
||||
// https://github.com/sporto/assets-webpack-plugin#options
|
||||
new AssetsPlugin({
|
||||
path: path.resolve(__dirname, './build'),
|
||||
filename: 'assets.json',
|
||||
prettyPrint: true,
|
||||
}),
|
||||
assetPlugin,
|
||||
|
||||
// Webpack Bundle Analyzer
|
||||
// https://github.com/th0r/webpack-bundle-analyzer
|
||||
...isAnalyze ? [new BundleAnalyzerPlugin()] : [],
|
||||
...analyze ? [new BundleAnalyzerPlugin({ analyzerPort: 8889 })] : [],
|
||||
],
|
||||
|
||||
optimization: {
|
||||
|
@ -155,19 +168,25 @@ export default {
|
|||
|
||||
vendor: {
|
||||
name: 'vendor',
|
||||
chunks: (chunk) => chunk.name === 'client',
|
||||
test: /node_modules/,
|
||||
chunks: (chunk) => chunk.name.startsWith('client'),
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
},
|
||||
three: {
|
||||
test: /[\\/]node_modules[\\/]three[\\/]/,
|
||||
name: 'three',
|
||||
chunks: 'all',
|
||||
test: /[\\/]node_modules[\\/]three[\\/]/,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
bail: !isDebug,
|
||||
|
||||
cache: isDebug,
|
||||
cache: true,
|
||||
};
|
||||
}
|
||||
|
||||
export default buildWebpackClientConfig(
|
||||
process.argv.includes('--debug'),
|
||||
process.argv.includes('--analyse') || process.argv.includes('--analyze'),
|
||||
'default',
|
||||
);
|
||||
|
||||
|
|
237
webpack.config.client.babel.js.old
Normal file
237
webpack.config.client.babel.js.old
Normal file
|
@ -0,0 +1,237 @@
|
|||
/**
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import webpack from 'webpack';
|
||||
import AssetsPlugin from 'assets-webpack-plugin';
|
||||
import TtagWebpackPlugin from 'ttag-webpack-plugin';
|
||||
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
|
||||
|
||||
import pkg from './package.json';
|
||||
|
||||
const isDebug = process.argv.includes('--debug');
|
||||
const VERBOSE = false;
|
||||
const isAnalyze = process.argv.includes('--analyze')
|
||||
|| process.argv.includes('--analyse');
|
||||
|
||||
// activate for deprecation tracking
|
||||
// process.traceDeprecation = true;
|
||||
|
||||
const babelPlugins = [
|
||||
'@babel/transform-flow-strip-types',
|
||||
['@babel/plugin-proposal-decorators', { legacy: true }],
|
||||
'@babel/plugin-proposal-function-sent',
|
||||
'@babel/plugin-proposal-export-namespace-from',
|
||||
'@babel/plugin-proposal-numeric-separator',
|
||||
'@babel/plugin-proposal-throw-expressions',
|
||||
['@babel/plugin-proposal-class-properties', { loose: true }],
|
||||
'@babel/proposal-object-rest-spread',
|
||||
// react-optimize
|
||||
'@babel/transform-react-constant-elements',
|
||||
'@babel/transform-react-inline-elements',
|
||||
'transform-react-remove-prop-types',
|
||||
'transform-react-pure-class-to-function',
|
||||
];
|
||||
|
||||
/*
|
||||
* get all available languages
|
||||
*/
|
||||
const langDir = path.resolve(__dirname, 'i18n');
|
||||
const langs = fs.readdirSync(langDir)
|
||||
.filter((e) => e.endsWith('.po'))
|
||||
.map((l) => l.slice(0, -3));
|
||||
|
||||
/*
|
||||
* create list of translations for ttag-webpack-plugin
|
||||
*/
|
||||
const translations = {};
|
||||
for (let i = 0; i < langs.length; i += 1) {
|
||||
const lang = langs[i];
|
||||
translations[lang] = path.resolve(langDir, `${lang}.po`);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cache Groups for splitChunks
|
||||
* (edit cache groups here, make sure that chunks is based on name)
|
||||
*/
|
||||
const cacheGroups = {
|
||||
default: false,
|
||||
defaultVendors: false,
|
||||
|
||||
vendor: {
|
||||
name: 'vendor',
|
||||
chunks: (chunk) => chunk.name === 'client',
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
},
|
||||
three: {
|
||||
name: 'three',
|
||||
chunks: (chunk) => (chunk.name === 'globe' || chunk.name === 'voxel'),
|
||||
test: /[\\/]node_modules[\\/]three[\\/]/,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* automatically add Cache Groups for languages based on
|
||||
* manually set cacheGroups
|
||||
*/
|
||||
const groups = Object.keys(cacheGroups);
|
||||
for (let u = 0; u < groups.length; u += 1) {
|
||||
const group = cacheGroups[groups[u]];
|
||||
if (!group.test) continue;
|
||||
|
||||
for (let i = 0; i < langs.length; i += 1) {
|
||||
const lang = langs[i];
|
||||
/* add lang */
|
||||
const key = `${groups[u]}-${lang}`;
|
||||
const name = `${group.name}-${lang}`;
|
||||
const { test, chunks } = group;
|
||||
|
||||
cacheGroups[key] = {
|
||||
name,
|
||||
chunks: (chunk) => {
|
||||
if (!chunk.name.endsWith(`-${lang}`)) {
|
||||
return false;
|
||||
}
|
||||
return chunks({
|
||||
name: chunk.name.slice(0, -lang.length - 1),
|
||||
});
|
||||
},
|
||||
test,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default {
|
||||
name: 'client',
|
||||
target: 'web',
|
||||
|
||||
context: __dirname,
|
||||
mode: (isDebug) ? 'development' : 'production',
|
||||
devtool: 'source-map',
|
||||
|
||||
entry: {
|
||||
client: ['./src/client.js'],
|
||||
globe: ['./src/globe.js'],
|
||||
},
|
||||
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'build', 'public', 'assets'),
|
||||
publicPath: '/assets/',
|
||||
pathinfo: VERBOSE,
|
||||
filename: isDebug ? '[name].js' : '[name].[chunkhash:8].js',
|
||||
chunkFilename: isDebug ? '[name].chunk.js' : '[name].[chunkhash:8].js',
|
||||
},
|
||||
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.svg$/,
|
||||
use: [
|
||||
{
|
||||
loader: 'babel-loader',
|
||||
},
|
||||
{
|
||||
loader: 'react-svg-loader',
|
||||
options: {
|
||||
svgo: {
|
||||
plugins: [
|
||||
{
|
||||
removeViewBox: false,
|
||||
},
|
||||
{
|
||||
removeDimensions: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
jsx: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.(js|jsx|ts|tsx)$/,
|
||||
loader: 'babel-loader',
|
||||
include: [
|
||||
path.resolve(__dirname, 'src'),
|
||||
],
|
||||
options: {
|
||||
cacheDirectory: isDebug,
|
||||
babelrc: false,
|
||||
presets: [
|
||||
['@babel/preset-env', {
|
||||
targets: {
|
||||
browsers: pkg.browserslist,
|
||||
},
|
||||
modules: false,
|
||||
useBuiltIns: 'usage',
|
||||
corejs: {
|
||||
version: 3,
|
||||
},
|
||||
debug: false,
|
||||
}],
|
||||
'@babel/typescript',
|
||||
'@babel/react',
|
||||
],
|
||||
plugins: babelPlugins,
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.css/,
|
||||
use: ['style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
sourceMap: isDebug,
|
||||
modules: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
plugins: [
|
||||
// Define free variables
|
||||
// https://webpack.github.io/docs/list-of-plugins.html#defineplugin
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': isDebug ? '"development"' : '"production"',
|
||||
'process.env.BROWSER': true,
|
||||
}),
|
||||
|
||||
// make multiple bundles for each language
|
||||
new TtagWebpackPlugin({
|
||||
translations,
|
||||
}),
|
||||
|
||||
// Emit a file with assets paths
|
||||
// https://github.com/sporto/assets-webpack-plugin#options
|
||||
new AssetsPlugin({
|
||||
path: path.resolve(__dirname, 'build'),
|
||||
filename: 'assets.json',
|
||||
prettyPrint: true,
|
||||
}),
|
||||
|
||||
// Webpack Bundle Analyzer
|
||||
// https://github.com/th0r/webpack-bundle-analyzer
|
||||
...isAnalyze ? [new BundleAnalyzerPlugin()] : [],
|
||||
],
|
||||
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
name: false,
|
||||
cacheGroups,
|
||||
},
|
||||
},
|
||||
|
||||
bail: !isDebug,
|
||||
|
||||
cache: isDebug,
|
||||
};
|
|
@ -9,7 +9,6 @@ import GeneratePackageJsonPlugin from 'generate-package-json-webpack-plugin';
|
|||
import pkg from './package.json';
|
||||
|
||||
const isDebug = process.argv.includes('--debug');
|
||||
const VERBOSE = false;
|
||||
|
||||
const basePackageValues = {
|
||||
name: pkg.name,
|
||||
|
@ -54,8 +53,7 @@ export default {
|
|||
},
|
||||
|
||||
output: {
|
||||
pathinfo: VERBOSE,
|
||||
path: path.resolve(__dirname, './build'),
|
||||
path: path.resolve(__dirname, 'build'),
|
||||
libraryTarget: 'commonjs2',
|
||||
},
|
||||
|
||||
|
@ -69,7 +67,7 @@ export default {
|
|||
test: /\.(js|jsx|ts|tsx)$/,
|
||||
loader: 'babel-loader',
|
||||
include: [
|
||||
path.resolve(__dirname, './src'),
|
||||
path.resolve(__dirname, 'src'),
|
||||
],
|
||||
options: {
|
||||
cacheDirectory: isDebug,
|
||||
|
@ -121,9 +119,8 @@ export default {
|
|||
}),
|
||||
// create package.json for deployment
|
||||
new GeneratePackageJsonPlugin(basePackageValues, {
|
||||
debug: VERBOSE,
|
||||
sourcePackageFilenames: [
|
||||
path.resolve(__dirname, './package.json'),
|
||||
path.resolve(__dirname, 'package.json'),
|
||||
],
|
||||
}),
|
||||
],
|
||||
|
@ -133,8 +130,4 @@ export default {
|
|||
__filename: false,
|
||||
__dirname: false,
|
||||
},
|
||||
|
||||
bail: !isDebug,
|
||||
|
||||
cache: isDebug,
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue
Block a user