diff --git a/gulpfile.ts b/gulpfile.ts index 6591a7d69..906a48fcc 100644 --- a/gulpfile.ts +++ b/gulpfile.ts @@ -132,8 +132,11 @@ gulp.task('build:client', [ ]); gulp.task('webpack', done => { - const output = childProcess.execSync(Path.join('.', 'node_modules', '.bin', 'webpack') + ' --config webpack.config.ts', ); + const output = childProcess.execSync( + Path.join('.', 'node_modules', '.bin', 'webpack') + ' --config ./webpack/webpack.config.ts'); + console.log(output.toString()); + done(); }); diff --git a/webpack.config.ts b/webpack.config.ts deleted file mode 100644 index e550a0022..000000000 --- a/webpack.config.ts +++ /dev/null @@ -1,120 +0,0 @@ -/** - * webpack config - */ - -import * as fs from 'fs'; -import * as webpack from 'webpack'; -const StringReplacePlugin = require('string-replace-webpack-plugin'); -import * as yaml from 'js-yaml'; - -import version from './src/version'; -const constants = require('./src/const.json'); - -const languages = { - 'en': yaml.safeLoad(fs.readFileSync('./locales/en.yml', 'utf-8')), - 'ja': yaml.safeLoad(fs.readFileSync('./locales/ja.yml', 'utf-8')) -}; - -const native = languages.ja; - -const env = process.env.NODE_ENV; -const isProduction = env === 'production'; - -module.exports = (Object as any).entries(languages).map(([lang, locale]) => { - locale = Object.assign({}, native, locale); - - const pack /*: webpack.Configuration ← fuck wrong type definition!!! */ = { - name: lang, - entry: { - 'desktop': './src/web/app/desktop/script.js', - 'mobile': './src/web/app/mobile/script.js', - 'dev': './src/web/app/dev/script.js', - 'auth': './src/web/app/auth/script.js' - }, - module: { - rules: [ - { - enforce: 'pre', - test: /\.(tag|js)$/, - exclude: /node_modules/, - loader: StringReplacePlugin.replace({ - replacements: [ - { - pattern: /%i18n:(.+?)%/g, replacement: (_, key) => { - let text = locale; - const error = key.split('.').some(k => { - if (text.hasOwnProperty(k)) { - text = text[k]; - return false; - } else { - return true; - } - }); - if (error) { - console.warn(`key '${key}' not found in '${lang}'`); - return key; - } else { - return text.replace(/'/g, '\\\'').replace(/"/g, '\\"'); - } - } - } - ] - }) - }, - { - enforce: 'pre', - test: /\.tag$/, - exclude: /node_modules/, - loader: StringReplacePlugin.replace({ - replacements: [ - { pattern: /\$theme\-color\-foreground/g, replacement: () => constants.themeColorForeground }, - { pattern: /\$theme\-color/g, replacement: () => constants.themeColor }, - ] - }) - }, - { - test: /\.tag$/, - exclude: /node_modules/, - loader: 'riot-tag-loader', - query: { - hot: false, - style: 'stylus', - expr: false, - compact: true, - parserOptions: { - style: { - compress: true - } - } - } - }, - { - test: /\.styl$/, - exclude: /node_modules/, - use: [ - { loader: 'style-loader' }, - { loader: 'css-loader' }, - { loader: 'stylus-loader' } - ] - } - ] - }, - plugins: [ - new webpack.DefinePlugin({ - VERSION: JSON.stringify(version), - THEME_COLOR: JSON.stringify(constants.themeColor) - }), - new StringReplacePlugin() - ], - output: { - path: __dirname + '/built/web/assets', - filename: `[name].${version}.${lang}.js` - } - }; - - if (isProduction) { - //pack.plugins.push(new webpack.optimize.UglifyJsPlugin()); - } - - return pack; -}); diff --git a/webpack/langs.ts b/webpack/langs.ts new file mode 100644 index 000000000..409b25504 --- /dev/null +++ b/webpack/langs.ts @@ -0,0 +1,23 @@ +/** + * Languages Loader + */ + +import * as fs from 'fs'; +import * as yaml from 'js-yaml'; + +const loadLang = lang => yaml.safeLoad( + fs.readFileSync(`./locales/${lang}.yml`, 'utf-8')); + +const native = loadLang('ja'); + +const langs = Object.entries({ + 'en': loadLang('en'), + 'ja': native +}); + +langs.map(([, locale]) => { + // Extend native language (Japanese) + locale = Object.assign({}, native, locale); +}); + +export default langs; diff --git a/webpack/module/index.ts b/webpack/module/index.ts new file mode 100644 index 000000000..15f36557c --- /dev/null +++ b/webpack/module/index.ts @@ -0,0 +1,5 @@ +import rules from './rules'; + +export default (lang, locale) => ({ + rules: rules(lang, locale) +}); diff --git a/webpack/module/rules/i18n.ts b/webpack/module/rules/i18n.ts new file mode 100644 index 000000000..0539e97db --- /dev/null +++ b/webpack/module/rules/i18n.ts @@ -0,0 +1,34 @@ +/** + * Replace i18n texts + */ + +const StringReplacePlugin = require('string-replace-webpack-plugin'); + +export default (lang, locale) => ({ + enforce: 'pre', + test: /\.(tag|js)$/, + exclude: /node_modules/, + loader: StringReplacePlugin.replace({ + replacements: [ + { + pattern: /%i18n:(.+?)%/g, replacement: (_, key) => { + let text = locale; + const error = key.split('.').some(k => { + if (text.hasOwnProperty(k)) { + text = text[k]; + return false; + } else { + return true; + } + }); + if (error) { + console.warn(`key '${key}' not found in '${lang}'`); + return key; + } else { + return text.replace(/'/g, '\\\'').replace(/"/g, '\\"'); + } + } + } + ] + }) +}); diff --git a/webpack/module/rules/index.ts b/webpack/module/rules/index.ts new file mode 100644 index 000000000..2308f4e53 --- /dev/null +++ b/webpack/module/rules/index.ts @@ -0,0 +1,11 @@ +import i18n from './i18n'; +import themeColor from './theme-color'; +import tag from './tag'; +import stylus from './stylus'; + +export default (lang, locale) => [ + i18n(lang, locale), + themeColor(), + tag(), + stylus() +]; diff --git a/webpack/module/rules/stylus.ts b/webpack/module/rules/stylus.ts new file mode 100644 index 000000000..dd1e4c321 --- /dev/null +++ b/webpack/module/rules/stylus.ts @@ -0,0 +1,13 @@ +/** + * Stylus support + */ + +export default () => ({ + test: /\.styl$/, + exclude: /node_modules/, + use: [ + { loader: 'style-loader' }, + { loader: 'css-loader' }, + { loader: 'stylus-loader' } + ] +}); diff --git a/webpack/module/rules/tag.ts b/webpack/module/rules/tag.ts new file mode 100644 index 000000000..706af35b4 --- /dev/null +++ b/webpack/module/rules/tag.ts @@ -0,0 +1,20 @@ +/** + * Riot tags + */ + +export default () => ({ + test: /\.tag$/, + exclude: /node_modules/, + loader: 'riot-tag-loader', + query: { + hot: false, + style: 'stylus', + expr: false, + compact: true, + parserOptions: { + style: { + compress: true + } + } + } +}); diff --git a/webpack/module/rules/theme-color.ts b/webpack/module/rules/theme-color.ts new file mode 100644 index 000000000..7ee545191 --- /dev/null +++ b/webpack/module/rules/theme-color.ts @@ -0,0 +1,25 @@ +/** + * Theme color provider + */ + +const StringReplacePlugin = require('string-replace-webpack-plugin'); + +const constants = require('../../../src/const.json'); + +export default () => ({ + enforce: 'pre', + test: /\.tag$/, + exclude: /node_modules/, + loader: StringReplacePlugin.replace({ + replacements: [ + { + pattern: /\$theme\-color\-foreground/g, + replacement: () => constants.themeColorForeground + }, + { + pattern: /\$theme\-color/g, + replacement: () => constants.themeColor + }, + ] + }) +}); diff --git a/webpack/plugins/const.ts b/webpack/plugins/const.ts new file mode 100644 index 000000000..ccfcb4526 --- /dev/null +++ b/webpack/plugins/const.ts @@ -0,0 +1,13 @@ +/** + * Constant Replacer + */ + +import * as webpack from 'webpack'; + +import version from '../../src/version'; +const constants = require('../../src/const.json'); + +export default () => new webpack.DefinePlugin({ + VERSION: JSON.stringify(version), + THEME_COLOR: JSON.stringify(constants.themeColor) +}); diff --git a/webpack/plugins/index.ts b/webpack/plugins/index.ts new file mode 100644 index 000000000..0692b9f8d --- /dev/null +++ b/webpack/plugins/index.ts @@ -0,0 +1,19 @@ +const StringReplacePlugin = require('string-replace-webpack-plugin'); + +import constant from './const'; + +const env = process.env.NODE_ENV; +const isProduction = env === 'production'; + +export default () => { + const plugins = [ + constant(), + new StringReplacePlugin() + ]; + + if (isProduction) { + //plugins.push(new webpack.optimize.UglifyJsPlugin()); + } + + return plugins; +}; diff --git a/webpack/webpack.config.ts b/webpack/webpack.config.ts new file mode 100644 index 000000000..50733a6cf --- /dev/null +++ b/webpack/webpack.config.ts @@ -0,0 +1,35 @@ +/** + * webpack configuration + */ + +import module_ from './module'; +import plugins from './plugins'; + +import langs from './langs'; +import version from '../src/version'; + +module.exports = langs.map(([lang, locale]) => { + // Chunk name + const name = lang; + + // Entries + const entry = { + 'desktop': './src/web/app/desktop/script.js', + 'mobile': './src/web/app/mobile/script.js', + 'dev': './src/web/app/dev/script.js', + 'auth': './src/web/app/auth/script.js' + }; + + const output = { + path: __dirname + '/../built/web/assets', + filename: `[name].${version}.${lang}.js` + }; + + return { + name, + entry, + module: module_(lang, locale), + plugins: plugins(), + output + }; +});