From b1cbcd88057df6bd0e861b79f2e538c48c7266c6 Mon Sep 17 00:00:00 2001
From: justin <978336184@qq.com>
Date: Wed, 22 Dec 2021 18:19:05 +0800
Subject: [PATCH] vue ssr MiniCssExtractPlugin error
https://github.com/webpack-contrib/mini-css-extract-plugin/issues/90
---
build/webpack.base.conf.js | 219 ++++++++++++++++++-----------------
build/webpack.client.conf.js | 9 +-
build/webpack.server.conf.js | 8 +-
package-lock.json | 48 ++++++++
package.json | 2 +
src/entry-client.js | 11 ++
src/views/Home.vue | 9 +-
7 files changed, 190 insertions(+), 116 deletions(-)
diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js
index 5347d55..eba7127 100644
--- a/build/webpack.base.conf.js
+++ b/build/webpack.base.conf.js
@@ -5,121 +5,122 @@ const { VueLoaderPlugin } = require('vue-loader');
const ESLintPlugin = require('eslint-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
-module.exports = {
- performance: {
- // 资源文件最大限制大小warning提示 1000kb
- maxAssetSize: 1000 * 1024,
- maxEntrypointSize: 1000 * 1024,
- },
- output: {
- filename: '[name].[chunkhash].js',
- chunkFilename: '[name].[chunkhash].js',
- path: path.resolve(__dirname, '../dist'),
- publicPath: '',
- },
- module: {
- rules: [
- {
- test: /\.vue$/,
- loader: 'vue-loader'
- },
- {
- test: /\.m?js$/,
- loader: 'babel-loader',
- exclude: file => {
- return /node_modules/.test(file)
- }
- },
- {
- test: /\.s?css$/i,
- use: [
- {
- loader: MiniCssExtractPlugin.loader,
- options: {
- publicPath: '../'
- }
- },
- {
- loader: "css-loader",
- options: { importLoaders: 1 },
- },
- {
- loader: "postcss-loader",
- options: {
- postcssOptions: {
- plugins: [
- [
- "autoprefixer",
- {
- // Options
- },
+module.exports = platform => {
+ return {
+ performance: {
+ // 资源文件最大限制大小warning提示 1000kb
+ maxAssetSize: 1000 * 1024,
+ maxEntrypointSize: 1000 * 1024,
+ },
+ output: {
+ filename: '[name].[chunkhash].js',
+ chunkFilename: '[name].[chunkhash].js',
+ path: path.resolve(__dirname, '../dist'),
+ publicPath: '',
+ },
+ module: {
+ rules: [
+ {
+ test: /\.vue$/,
+ loader: 'vue-loader',
+ options: {
+ extractCSS: true
+ }
+ },
+ {
+ test: /\.m?js$/,
+ loader: 'babel-loader',
+ exclude: file => {
+ return /node_modules/.test(file)
+ }
+ },
+ {
+ test: /\.s?css$/i,
+ use: [
+ platform == 'server' ? {
+ loader: 'null-loader'
+ } : {
+ loader: MiniCssExtractPlugin.loader,
+ options: {
+ publicPath: '../'
+ }
+ },
+ {
+ loader: "css-loader",
+ options: { importLoaders: 1 },
+ },
+ {
+ loader: "postcss-loader",
+ options: {
+ postcssOptions: {
+ plugins: [
+ [
+ "autoprefixer",
+ {
+ // Options
+ },
+ ],
],
- ],
+ },
},
},
+ 'sass-loader'
+ ],
+ },
+ {
+ test: /\.(png|svg|jpg|jpeg|gif|webp)$/i,
+ // asset 自动地在 asset/resource 和 asset/inline 之间进行选择, 默认size < 8kb 实行asset/inline
+ type: 'asset',
+ parser: {
+ dataUrlCondition: {
+ maxSize: 4 * 1024 // 4kb
+ }
+ },
+ generator: {
+ filename: 'images/[name].[hash][ext]',
},
- 'sass-loader'
- ],
- },
- {
- test: /\.(png|svg|jpg|jpeg|gif|webp)$/i,
- // asset 自动地在 asset/resource 和 asset/inline 之间进行选择, 默认size < 8kb 实行asset/inline
- type: 'asset',
- parser: {
- dataUrlCondition: {
- maxSize: 4 * 1024 // 4kb
- }
},
- generator: {
- filename: 'images/[name].[hash][ext]',
+ {
+ test: /\.(woff|woff2|eot|ttf|otf)$/i,
+ // asset 自动地在 asset/resource 和 asset/inline 之间进行选择, 默认size < 8kb 实行asset/inline
+ type: 'asset',
+ parser: {
+ dataUrlCondition: {
+ maxSize: 4 * 1024 // 4kb
+ }
+ },
+ generator: {
+ filename: 'fonts/[name].[hash][ext]',
+ },
},
- },
- {
- test: /\.(woff|woff2|eot|ttf|otf)$/i,
- // asset 自动地在 asset/resource 和 asset/inline 之间进行选择, 默认size < 8kb 实行asset/inline
- type: 'asset',
- parser: {
- dataUrlCondition: {
- maxSize: 4 * 1024 // 4kb
+ ],
+ },
+ plugins: [
+ new CopyWebpackPlugin({
+ patterns: [
+ {
+ from: path.resolve(__dirname, '../static'),
+ to: path.resolve(__dirname, '../dist'),
+ noErrorOnMissing: true
}
- },
- generator: {
- filename: 'fonts/[name].[hash][ext]',
- },
- },
+ ]
+ }),
+ new ESLintPlugin(),
+ new VueLoaderPlugin(),
+ // 注入webpack编译时js中的全局变量
+ new webpack.DefinePlugin({
+ 'process.env.THEME': JSON.stringify(process.env.THEME)
+ })
],
- },
- plugins: [
- new CopyWebpackPlugin({
- patterns: [
- {
- from: path.resolve(__dirname, '../static'),
- to: path.resolve(__dirname, '../dist'),
- noErrorOnMissing: true
- }
- ]
- }),
- new ESLintPlugin(),
- new VueLoaderPlugin(),
- // 提取style生成 css文件
- new MiniCssExtractPlugin({
- filename: 'css/[name].[contenthash:8].css',
- chunkFilename: 'css/[id][contenthash:8].css',
- ignoreOrder: true
- }),
- // 注入webpack编译时js中的全局变量
- new webpack.DefinePlugin({
- 'process.env.THEME': JSON.stringify(process.env.THEME)
- })
- ],
- resolve: {
- // 路径别名以及文件默认查找后缀数组
- alias: {
- '@': path.resolve(__dirname, '../src'),
- '@styles': path.resolve(__dirname, '../src/styles'),
- '@images': path.resolve(__dirname, '../src/images'),
- '@theme': path.resolve(__dirname, `../src/styles/themes/${process.env.THEME}.scss`)
- },
- extensions: ['.js', '.ts', '.jsx', '.tsx', '.vue', '.json'],
- }
+ resolve: {
+ // 路径别名以及文件默认查找后缀数组
+ alias: {
+ '@': path.resolve(__dirname, '../src'),
+ '@styles': path.resolve(__dirname, '../src/styles'),
+ '@images': path.resolve(__dirname, '../src/images'),
+ '@theme': path.resolve(__dirname, `../src/styles/themes/${process.env.THEME}.scss`)
+ },
+ extensions: ['.js', '.ts', '.jsx', '.tsx', '.vue', '.json'],
+ }
+ };
};
\ No newline at end of file
diff --git a/build/webpack.client.conf.js b/build/webpack.client.conf.js
index 1348d88..c0d81aa 100644
--- a/build/webpack.client.conf.js
+++ b/build/webpack.client.conf.js
@@ -1,9 +1,10 @@
const webpack = require('webpack');
const { merge } = require('webpack-merge');
-const baseConfig = require('./webpack.base.conf.js');
+const baseConfig = require('./webpack.base.conf.js')('client');
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
+const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = (env) => {
const isProd = env.NODE_ENV === 'production';
@@ -39,6 +40,12 @@ module.exports = (env) => {
mode: env.NODE_ENV,
entry: './src/entry-client.js',
plugins: [
+ // 提取style生成 css文件
+ new MiniCssExtractPlugin({
+ filename: 'css/[name].[contenthash:8].css',
+ chunkFilename: 'css/[id][contenthash:8].css',
+ ignoreOrder: true
+ }),
new webpack.DefinePlugin({
'process.env.VUE_ENV': '"client"'
}),
diff --git a/build/webpack.server.conf.js b/build/webpack.server.conf.js
index 7bc4636..a1edc2d 100644
--- a/build/webpack.server.conf.js
+++ b/build/webpack.server.conf.js
@@ -1,7 +1,7 @@
const webpack = require('webpack');
const { merge } = require('webpack-merge');
const nodeExternals = require('webpack-node-externals');
-const baseConfig = require('./webpack.base.conf.js');
+const baseConfig = require('./webpack.base.conf.js')('server');
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin');
module.exports = (env) => {
@@ -26,12 +26,12 @@ module.exports = (env) => {
// https://github.com/liady/webpack-node-externals
// 外置化应用程序依赖模块。可以使服务器构建速度更快,
// 并生成较小的 bundle 文件。
- externals: nodeExternals({
+ externals: [nodeExternals({
// 不要外置化 webpack 需要处理的依赖模块。
// 你可以在这里添加更多的文件类型。例如,未处理 *.vue 原始文件,
// 你还应该将修改 `global`(例如 polyfill)的依赖模块列入白名单
- allowlist: /\.css$/
- }),
+ allowlist: [/\.s?css$/, /\?vue&type=style/]
+ })],
// 这是将服务器的整个输出
// 构建为单个 JSON 文件的插件。
diff --git a/package-lock.json b/package-lock.json
index 2192ecf..1023402 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4389,6 +4389,11 @@
"integrity": "sha1-DdkM8SiO4dExO4cIHJpZMu5IUYo=",
"dev": true
},
+ "nprogress": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmmirror.com/nprogress/download/nprogress-0.2.0.tgz",
+ "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA=="
+ },
"nth-check": {
"version": "2.0.1",
"resolved": "https://registry.nlark.com/nth-check/download/nth-check-2.0.1.tgz",
@@ -4398,6 +4403,49 @@
"boolbase": "^1.0.0"
}
},
+ "null-loader": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npm.taobao.org/null-loader/download/null-loader-4.0.1.tgz",
+ "integrity": "sha1-jmO9Oi3TxkI2pGeUKGMu3QptvGo=",
+ "dev": true,
+ "requires": {
+ "loader-utils": "^2.0.0",
+ "schema-utils": "^3.0.0"
+ },
+ "dependencies": {
+ "json5": {
+ "version": "2.2.0",
+ "resolved": "https://registry.nlark.com/json5/download/json5-2.2.0.tgz",
+ "integrity": "sha1-Lf7+cgxrpSXZ69kJlQ8FFTFsiaM=",
+ "dev": true,
+ "requires": {
+ "minimist": "^1.2.5"
+ }
+ },
+ "loader-utils": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmmirror.com/loader-utils/download/loader-utils-2.0.2.tgz",
+ "integrity": "sha1-1uO0+4GHByGuTghoqxHdY4NowSk=",
+ "dev": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^2.1.2"
+ }
+ },
+ "schema-utils": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmmirror.com/schema-utils/download/schema-utils-3.1.1.tgz?cache=0&sync_timestamp=1637075997986&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fschema-utils%2Fdownload%2Fschema-utils-3.1.1.tgz",
+ "integrity": "sha1-vHTEtraZXB2I92qLd76nIZ4MgoE=",
+ "dev": true,
+ "requires": {
+ "@types/json-schema": "^7.0.8",
+ "ajv": "^6.12.5",
+ "ajv-keywords": "^3.5.2"
+ }
+ }
+ }
+ },
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.nlark.com/object-assign/download/object-assign-4.1.1.tgz?cache=0&sync_timestamp=1618847043548&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fobject-assign%2Fdownload%2Fobject-assign-4.1.1.tgz",
diff --git a/package.json b/package.json
index cabd124..f8a3386 100644
--- a/package.json
+++ b/package.json
@@ -27,6 +27,7 @@
"koa-static-cache": "^5.1.4",
"log4js": "^6.3.0",
"lru-cache": "^6.0.0",
+ "nprogress": "^0.2.0",
"vue": "^2.6.14",
"vue-router": "^3.5.3",
"vue-server-renderer": "^2.6.14",
@@ -52,6 +53,7 @@
"eslint-webpack-plugin": "^3.1.1",
"mini-css-extract-plugin": "^2.4.5",
"nodemon": "^2.0.15",
+ "null-loader": "^4.0.1",
"ora": "^6.0.1",
"postcss-import": "^14.0.2",
"postcss-loader": "^6.2.1",
diff --git a/src/entry-client.js b/src/entry-client.js
index 8a3074b..b9113f6 100644
--- a/src/entry-client.js
+++ b/src/entry-client.js
@@ -1,4 +1,8 @@
import { createApp } from './app';
+import NProgress from 'nprogress'; // progress bar
+import 'nprogress/nprogress.css'; // progress bar style
+
+NProgress.configure({ showSpinner: false }); // NProgress Configuration
// 客户端特定引导逻辑……
@@ -55,6 +59,8 @@ router.beforeEach((to, from, next) => {
const whiteList = store.state.whiteList;
const loginName = store.state.loginName;
+ NProgress.start();
+
if (to.path !== '/login' && !loginName) {
if (!whiteList.includes(to.path)) {
return next(`/login?redirect=${to.fullPath}`);
@@ -91,4 +97,9 @@ router.beforeEach((to, from, next) => {
});
}
});
+});
+
+router.afterEach(() => {
+ console.log(NProgress);
+ NProgress.done(); // finish progress bar
});
\ No newline at end of file
diff --git a/src/views/Home.vue b/src/views/Home.vue
index fc0cf0d..8572fbd 100644
--- a/src/views/Home.vue
+++ b/src/views/Home.vue
@@ -4,7 +4,7 @@