开发环境正常
配置如下
webpack.base.config
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack');
const VueLoaderPlugin = require('vue-loader/lib/plugin'); // vue-loader需要引入
const AddAssetsHtmlPlugin = require('add-asset-html-webpack-plugin'); // 把dll文件增加到html
const HappyPack = require('happypack');
const happyThreedPool = HappyPack.ThreadPool({ size: 5 }) // 同享进程池,size代表子程个数
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // webpack4使用MiniCssExtractPlugin代替ExtractTextPlugin, 分离css
console.log(MiniCssExtractPlugin.loader);
function pathResolve(param) {
return path.resolve(__dirname, param)
}
// const extractCSS = new ExtractTextPlugin('assets/css/[name]_[md5:contenthash:hex:8].css');
// const extractSASS = new ExtractTextPlugin('assets/css/[name]-two.css');
module.exports = {
// devtool: 'eval-source-map',
//Resolve 配置Webpack如何寻找模块所对应的文件
resolve: {
// 别名
//使用alias 将导入vue 的语句换成直接使用单独、完整的vue.min.js 文件,减少耗时的递归解析操作
alias: {
'@': pathResolve('../src'), // 使用绝对路径
'vue': pathResolve('../node_modules/vue/dist/vue.min.js')
},
//默认 自动解析确定的扩展,能够使用户在引入模块时不带扩展
extensions: [".js", ".json", ".vue"],
// 第三方模块位置,使用绝对路径减少搜搜
modules: [pathResolve('../node_modules')] //TODO在这里路径写错了导致找不到模块
},
externals: {
// ElementUi: 'element-ui'
},// 防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖
module: {
rules: [
{
test: /\.js$/,
use: ['happypack/loader?id=happyBabel'],
exclude: pathResolve('../node_modules')
},
// {
// test: /\.scss$/,
// use: ExtractTextPlugin.extract({
// fallback: 'vue-style-loader',
// use: ['css-loader', 'sass-loader']
// })
// },
// {
// test: /\.css$/,
// use: ExtractTextPlugin.extract({
// fallback: 'vue-style-loader',
// use: ['css-loader']
// })
// },
{
test: /\.vue$/,
// loader: 'happypack/loader?id=happyBabel'
loader: 'vue-loader'
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: process.env.NODE_ENV === 'development'
}
},
'css-loader',
'sass-loader'
]
},
{
test: /\.(png|jpg|gif|svg)(\?.*)$/,
use: [
{
loader: 'file-loader',
options: {
name: 'assets/img/[name].[hash:7].[ext]'
}
},
{
loader: 'image-webpack-loader',
options: {
mozjpeg: {
progressive: true,
quality: 65
},
// optipng.enabled: false will disable optipng
optipng: {
enabled: false,
},
pngquant: {
quality: [0.65, 0.90],
speed: 4
},
gifsicle: {
interlaced: false,
},
// the webp option will enable WEBP
webp: {
quality: 75
}
}
}
]
},
{
// 对于图片资源,当文件体积小于10kb时,将其生成为base64,直接插入html中
// 当大于10kb时,将图片名称进行按照命名规则进行更改
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
name: 'assets/img/[name].[hash:7].[ext]'
// name: 'assets/img/[name].[hash:7].[ext]'
}
}
]
}, {
// 字体资源打包规则,与图片资源相同
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000, // 超过限制会使用file-loader或者fallback配置的loader
name: 'assets/font/[name].[hash:7].[ext]'
}
}
],
noParse: /jquery|lodash/ // 忽略对部分没采用模块化的文件的递归解析和处理
},
plugins: [
new VueLoaderPlugin(),
new CleanWebpackPlugin(),
//告诉Webpack 使用了哪些动态链接库
new webpack.DllReferencePlugin({
// context: '../',
manifest: require('../public/vendor/vue.manifest.json'),
}),
new webpack.DllReferencePlugin({
// context: '../',
manifest: require('../public/vendor/polyfill.manifest.json'),
}),
new HtmlWebpackPlugin({
title: 'webpack vue',
template: './public/index.html',
filename: 'index.html',
favicon: './public/favicon.ico'
}),
new AddAssetsHtmlPlugin({ filepath: pathResolve('../public/vendor/*.dll.js') }),
new HappyPack({
//用id来标识 happypack处理那里类文件
id: 'happyBabel',
//如何处理 用法和loader 的配置一样
loaders: [{
loader: 'babel-loader?cacheDirectory=true'
}],
// 共享进程池
threadPool: happyThreedPool,
// 允许happyPack 输出日志
verbose: true
}),
// extractCSS,
new MiniCssExtractPlugin({
filename: 'assets/css/[name]_[contenthash:8].css',
chunkFilename: 'assets/css/[name]_[chunkhash:8].css'
})
],
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30,
cacheGroups: {
// 单页提取公共js
utils: {
test: /[\\/]src[\\/]utils[\\/]/,
chunks: 'all',
//minChunks: 2, // 共享最少使用模块数量
priority: 1,
reuseExistingChunk: true, // 重用该chunk
name: 'utils'
},
vendors: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
priority: -10
},
// styles: {
// name: 'styles',
// test: /\.css$/,
// chunks: 'all',
// enforce: true
// }
}
}
}
};
webpack.dev.config.js
const baseConfig = require('./webpack.base.config');
const webpackMerge = require('webpack-merge');
const webpack = require('webpack');
const path = require('path');
function pathResolve(param) {
return path.resolve(__dirname, param)
}
module.exports = webpackMerge(baseConfig, {
entry: ['./src/main.js','webpack-hot-middleware/client' ],
output: {
path: pathResolve('../dist'),
filename: 'assets/js/[name].[hash:8].js',
chunkFilename: 'assets/js/[name].[chunkhash:8].js',
publicPath: '/'
},
mode: 'development',
devtool: 'cheap-eval-source-map',
plugins: [
new webpack.HotModuleReplacementPlugin()
],
stats: {
modules: false,
children: false,
chunks: false,
chunkModules: false
}
})
index.vue样式
`
<style lang="scss" scoped>
.layout {
width: 100%;
height: 100%;
.layout-main {
background-color: #ff0000;
}
.layout-footer {
height: 50px;
background-color: #00ff00;
}
}
</style>~~~~
`
结果打包后正常输出文件如下:
main.css中有vue组件的样式
`
.layout[data-v-69de1e74] {
width: 100%;
height: 100%;
}
.layout .layout-main[data-v-69de1e74] {
background-color: #ff0000;
}
.layout .layout-footer[data-v-69de1e74] {
height: 50px;
background-color: #00ff00;
}
h1[data-v-7ba5bd90] {
color: "#ff0000";
}
.box[data-v-7ba5bd90] {
width: 200px;
height: 200px;
background: url(/assets/img/echarts.47f4e1e.png) no-repeat center;
background-size: contain;
}
* {
margin: 0;
padding: 0; }
html, body {
width: 100%;
height: 100%; }
`
生产环境
webpack.prod.js
const baseConfig = require('./webpack.base.config');
const webpackMerge = require('webpack-merge');
const ParalleUglifyPlugin = require('webpack-parallel-uglify-plugin'); //webpack4 使用terser代替uglify,为了支持ES6
const TerserPlugin = require('terser-webpack-plugin'); // 使用TerserPlugin覆盖默认压缩工具(minimizer-基于terser)
const OpitimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'); // 压缩css
const webpack = require('webpack');
const path = require('path');
function pathResolve(param) {
return path.resolve(__dirname, param)
}
module.exports = webpackMerge(baseConfig, {
entry: './src/main.js',
output: {
path: pathResolve('../dist'),
filename: 'assets/js/[name].[chunkhash:8].js',
chunkFilename: 'assets/js/[name].[chunkhash:8].js',
publicPath: '/'
},
mode: 'production',
devtool: 'none',
plugins: [
// webpack内置了uglify.js压缩js,但是只能一个一个的压缩
new webpack.HashedModuleIdsPlugin() // 保持moduleId不变,main中引入其他module,会导致moduele顺序变化,这样vender中所有moduled的iD会变化会导致chunkhash变化,从而导致缓存失效
],
optimization: {
minimizer: [
new TerserPlugin({
cache: true, // 启用缓存
parallel: true // 并行压缩 默认为cpu-1
}),
new OpitimizeCssAssetsWebpackPlugin({})
]
}
})
问题main.css中vue组件的样式不见了
`*{margin:0;padding:0}body,html{width:100%;height:100%}`
不怎么回事求大声解答
自己已经解决,treeshaking把.vue文件的css去掉了,在package.json加sideEffects加上vue,或者在bable-loader加上sideEffects:false