diff --git a/package.json b/package.json
index fee512c7f..906d512dc 100644
--- a/package.json
+++ b/package.json
@@ -118,6 +118,7 @@
 		"gulp-uglify": "3.0.0",
 		"gulp-util": "3.0.8",
 		"highlight.js": "9.12.0",
+		"html-minifier": "^3.5.9",
 		"inquirer": "5.0.1",
 		"is-root": "1.0.0",
 		"is-url": "1.2.2",
diff --git a/webpack/module/rules/base64.ts b/webpack/module/rules/base64.ts
index 529816bd2..6d7eaddeb 100644
--- a/webpack/module/rules/base64.ts
+++ b/webpack/module/rules/base64.ts
@@ -7,7 +7,7 @@ const StringReplacePlugin = require('string-replace-webpack-plugin');
 
 export default () => ({
 	enforce: 'pre',
-	test: /\.(tag|js)$/,
+	test: /\.(vue|js)$/,
 	exclude: /node_modules/,
 	loader: StringReplacePlugin.replace({
 		replacements: [{
diff --git a/webpack/module/rules/collapse-spaces.ts b/webpack/module/rules/collapse-spaces.ts
new file mode 100644
index 000000000..48fd57f01
--- /dev/null
+++ b/webpack/module/rules/collapse-spaces.ts
@@ -0,0 +1,20 @@
+import * as fs from 'fs';
+const minify = require('html-minifier').minify;
+const StringReplacePlugin = require('string-replace-webpack-plugin');
+
+export default () => ({
+	enforce: 'pre',
+	test: /\.vue$/,
+	exclude: /node_modules/,
+	loader: StringReplacePlugin.replace({
+		replacements: [{
+			pattern: /^<template>([\s\S]+?)\r?\n<\/template>/, replacement: html => {
+				return minify(html, {
+					collapseWhitespace: true,
+					collapseInlineTagWhitespace: true,
+					keepClosingSlash: true
+				});
+			}
+		}]
+	})
+});
diff --git a/webpack/module/rules/index.ts b/webpack/module/rules/index.ts
index 093f07330..c63da7112 100644
--- a/webpack/module/rules/index.ts
+++ b/webpack/module/rules/index.ts
@@ -6,8 +6,10 @@ import themeColor from './theme-color';
 import vue from './vue';
 import stylus from './stylus';
 import typescript from './typescript';
+import collapseSpaces from './collapse-spaces';
 
 export default lang => [
+	collapseSpaces(),
 	i18n(lang),
 	license(),
 	fa(),