diff --git a/build/webpack.base.config.js b/build/webpack.base.config.js index b625723..d395844 100644 --- a/build/webpack.base.config.js +++ b/build/webpack.base.config.js @@ -1,150 +1,152 @@ const path = require("path") const webpack = require("webpack") const FriendlyErrorsPlugin = require("friendly-errors-webpack-plugin") const StringReplacePlugin = require("string-replace-webpack-plugin") const StyleLintPlugin = require("stylelint-webpack-plugin") const Vue = require("vue") const VueI18n = require("vue-i18n") const config = require("../config") const messages = { main: require(`../i18n/${config.language.filename}`), fallback: config.fallbackLanguage ? require(`../i18n/${config.fallbackLanguage.filename}`) : null } Vue.use(VueI18n) i18n = new VueI18n({ locale: "main", fallbackLocale: messages.fallback ? "fallback" : null, messages }) const commonPlugins = [ new StringReplacePlugin(), new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify(config.nodeEnv), "PRODUCTION": config.isProduction, "LANGUAGE_MAIN_FILENAME": JSON.stringify(config.language.filename), "LANGUAGE_FALLBACK_FILENAME": config.fallbackLanguage ? JSON.stringify(config.fallbackLanguage.filename) : null, "LANGUAGE_ISRTL": config.language.isRTL, "process.env.RUNNING_ENV": JSON.stringify(config.runningEnv), "process.env.USE_CERTS": JSON.stringify(config.useCerts), "process.env.CERTS_CA": JSON.stringify(config.certsCa), "process.env.CERTS_CERT": JSON.stringify(config.certsCert), "process.env.CERTS_KEY": JSON.stringify(config.certsKey) }), new StyleLintPlugin({ files: ["src/**/*.vue", "src/**/*.scss"] }) ] const doI18n = StringReplacePlugin.replace({ replacements: [{ pattern: /\$ts\((.+)\)/g, replacement: function(fullMatch, params, offset, string) { params = params.split(",").map((p) => eval(p)) if (i18n.tc(...params) === params[0]) { // check if the translation key is defined // We could have used i18n.te but it does not account for fallback languages // We are using this instead. Uglier but does the job if (config.isProduction) { throw new Error(`[i18n] Translation key "${params[0]}" does not exist`) } else { // just warn in development mode console.warn(`[i18n] Translation key "${params[0]}" does not exist`) } } return i18n.tc(...params) } }] }) module.exports = { devtool: config.isProduction ? false : "inline-source-map", entry: { app: "./src/entry-client.js" }, output: { path: path.resolve(__dirname, "../dist"), publicPath: "/dist/", filename: "js/[name].[chunkhash:16].js" }, + mode: config.isProduction ? "production" : "development", + resolve: { alias: { "static": path.resolve(__dirname, "../static"), "src": path.resolve(__dirname, "../src"), "components": path.resolve(__dirname, "../src/components"), "images": path.resolve(__dirname, "../src/images"), "router": path.resolve(__dirname, "../src/router"), "store": path.resolve(__dirname, "../src/store"), "styles": path.resolve(__dirname, "../src/styles"), "mixins": path.resolve(__dirname, "../src/mixins"), "views": path.resolve(__dirname, "../src/views"), "api": path.resolve(__dirname, "../src/api") }, extensions: [".js", ".vue", ".scss"] }, resolveLoader: { alias: { "scss-loader": "sass-loader" } }, module: { noParse: /es6-promise\.js$/, // avoid webpack shimming process rules: [ { enforce: "pre", test: /\.(vue|js)$/, loader: "eslint-loader", exclude: /node_modules/ }, { test: /\.vue$/, loader: "vue-loader", options: { preLoaders: { pug: doI18n, html: doI18n }, preserveWhitespace: false, postcss: [ require("autoprefixer")({ browsers: ["last 3 versions"] }), require("cssnano") ] } }, { test: /\.js$/, loader: "babel-loader", exclude: /node_modules/ }, { test: /\.(png|jpe?g|gif|svg|ico)(\?.*)?$/, loader: "url-loader", options: { limit: 10000, name: "img/[name].[hash:16].[ext]" } } ] }, performance: { maxEntrypointSize: 250000, hints: config.isProduction ? "warning" : false }, plugins: config.isProduction ? commonPlugins : commonPlugins.concat([ new FriendlyErrorsPlugin() ]) } diff --git a/build/webpack.client.config.js b/build/webpack.client.config.js index 16519b6..ed2596f 100644 --- a/build/webpack.client.config.js +++ b/build/webpack.client.config.js @@ -1,106 +1,114 @@ const webpack = require("webpack") const merge = require("webpack-merge") const HTMLPlugin = require("html-webpack-plugin") const HtmlWebpackHarddiskPlugin = require("html-webpack-harddisk-plugin") const SWPrecachePlugin = require("sw-precache-webpack-plugin") -const BabiliPlugin = require("babili-webpack-plugin"); +//const BabiliPlugin = require("babili-webpack-plugin"); const base = require("./webpack.base.config") const config = require("../config") const VueSSRClientPlugin = require("vue-server-renderer/client-plugin") // minify options to be used in production mode // https://github.com/kangax/html-minifier#options-quick-reference const minifyOptions = { collapseWhitespace: true, removeComments: true, ignoreCustomComments: [/vue-ssr-outlet/] } const clientConfig = merge(base, { plugins: [ // strip dev-only code in Vue source new webpack.DefinePlugin({ "process.env.VUE_ENV": "'client'", "process.env.API_HOSTNAME": JSON.stringify(config.clientApiHostname), "process.env.KEYCLOAK_FRONTEND_CLIENT_ID": JSON.stringify(config.clientAuthId), "process.env.KEYCLOAK_AUTH_REALM": JSON.stringify(config.clientAuthRealm), "process.env.AUTH_HOSTNAME": JSON.stringify(config.clientAuthHostname) }), // generate output HTML new HTMLPlugin({ template: "src/index.template.html", minify: config.isProduction ? minifyOptions : {}, alwaysWriteToDisk: false, config }), // generate afterLogin HTML new HTMLPlugin({ filename: "afterLogin.html", template: "src/afterLogin.template.html", minify: config.isProduction ? minifyOptions : {}, inject: false, alwaysWriteToDisk: true, config }), new HtmlWebpackHarddiskPlugin(), new VueSSRClientPlugin() ] }) -if (config.isProduction) { +// Minifying JS is handled by "mode: production" +/*if (config.isProduction) { clientConfig.plugins.push( // minify JS new BabiliPlugin() ) -} +}*/ +// WIP: splitChunks optimization if necessary if (!config.isTesting) { + clientConfig.optimization = { + splitChunks: { + // Enable optimization for initial chunks too + chunks: "all" + } + } /*clientConfig.plugins.push( // extract vendor chunks for better caching // https://github.com/Narkoleptika/webpack-everything/commit/b7902f60806cf40b9d1abf8d6bb2a094d924fff7 new webpack.optimize.CommonsChunkPlugin({ name: "vendor", minChunks: function(module) { return module.context && module.context.indexOf("node_modules") !== -1 } }), // any other js goes here new webpack.optimize.CommonsChunkPlugin({ name: "manifest" }) )*/ - //clientConfig.optimization.push() } if (config.isProduction) { clientConfig.plugins.push( // auto generate service worker new SWPrecachePlugin({ cacheId: "wikitolearn", filename: "service-worker.js", staticFileGlobs: [ "dist/img/**/*", "dist/**/*.{html,js,css}" ], minify: true, dontCacheBustUrlsMatching: /./, runtimeCaching: [ { urlPattern: "/", handler: "networkFirst" }, { urlPattern: /\/api\/.*/, handler: "networkFirst" } ] }) - // On by default on "mode: production" //new webpack.optimize.ModuleConcatenationPlugin() ) + // On by default on "mode: production" + //clientConfig.optimization.concatenateModules = true } module.exports = clientConfig