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 @@ foo -