安装webpack4
yarn add webpack@4.41.6 webpack-cli@3.3.11 --dev 指定webpack4
配置文件
- webpack.commom.js存放公共的配置
- webpack.dev是开发独有的配置
- prod是线上独有的配置
loader
处理less, 压缩提取css
less(less less-loader css-loader)-> 压缩提取css(mini-css-extract-plugin) css 预处理 postcss-loader
yarn add less less-loader css-loader mini-css-extract-plugin postcss-loader postcss-preset-env --dev
webpack.common.js
entry: './src/main.js',
output: {
filename: 'js/main.js',
path: path.resolve('dist') // 输出文件路径, 必须使用绝对路径
},
module: {
rules: [
{
test: /\.less$/, // 处理less文件
use: [ // loader处理的顺序是从下到上
// 'style-loader' // 生成一个 style 标签,将 css-loader 处理后的字符串加载到界面中
MiniCssExtractPlugin.loader, // 将CSS提取到CSS文件中
'css-loader', // 将 css 代码处理为符合 commonjs 规范的代码,处理完成之后的内容是字符串
'less-loader' // 将 less 语法处理成 css 语法
]
},
{
test: /\.css/,
use: [
MiniCssExtractPlugin.loader, // 将CSS提取到CSS文件中
'css-loader', // 将 css 代码处理为符合 commonjs 规范的代码,处理完成之后的内容是字符串
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
// 下面的代码就好比是将我们当前配置中环境需要用到的 css处理语法加载进来
['postcss-preset-env']
]
}
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'css/build.css' // 提取css文件中
})
]
在package.json 文件的scripts 添加命令
"build:dev": "webpack --config webpack.common.js --mode development"
babel-loader
处理 JS babel-loader @babel/core 、@babel/preset-env 、 eslint-loader
yarn add babel-loader @babel/core @babel/preset-env babel-eslint --dev
webpack.common.js
{
test: /\.js$/, // js 处理(打包、校验、兼容、压缩)
loader: 'babel-loader',
exclude: /node_modules/, //node_modules 文件夹下的文件不处理
options: {
presets: [ // 预设 只是一个平台, 本身不处理
[
'@babel/preset-env', // 这个预设置只帮助我们完成一些基本的兼容 ,
{
useBuiltIns: 'usage', // usage 会根据配置的浏览器兼容,以及你代码中用到的 API 来进行 polyfill,实现了按需添加。
corejs: { version: 3 },
targets: { // 浏览器版本
chrome: '60',
firefox: '60',
ie: "9",
safari: '10',
edge: '17'
}
}
]
]
}
}
eslint-loader
yarn add eslint eslint-loader --dev
webpack.common.js
{
test: /\.js$/, // js 处理(校验)
enforce: 'pre', // loader 先执行
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
fix: true // 解决问题的代码
}
}
处理字体等
处理图片
yarn add file-loader url-loader --dev
webpack.common.js
{ // 处理图片
test: /\.(png|gif|jpg)$/, // 处理图片
loader: 'url-loader',
options: {
esModule: false,
limit: 2 * 1024,
outputPath: 'img'
}
},
vue-loader
yarn add vue-template-compiler vue-loader eslint-plugin-vue --dev
webpack.common.js
const VueLoaderPlugin = require('vue-loader/lib/plugin')
{
test: /\.vue$/,
exclude: /node_modules/,
loader: 'vue-loader'
}
new VueLoaderPlugin() // 配合vue-loader
处理生成html
yarn add html-webpack-plugin --dev
webpack.common.js
new HtmlWebpackPlugin({
template: './public/index.html',
publicPath: './', // 公共路径
}),
清理打包历史文件夹
yarn add clean-webpack-plugin --dev
new CleanWebpackPlugin(),
拷贝静态文件
yarn add copy-webpack-plugin --dev
webpack.common.js
new CopyWebpackPlgin({
patterns: [
{ from: 'src/assets/', to: './assets'},
'public'
]
})
开发配置:webpack.dev.js
服务器
yarn add webpack-dev-server --dev
"serve": "webpack-dev-server --open --config webpack.dev.js"
webpack.dev.js
const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.common')
const webpack = require('webapack')
const path = require('path')
// 合并公共配置
module.exports = merge(commonConfig, {
mode: 'development', // 开发模式
devtool: 'cheap-module-eval-source-map', // 调试
devServer: {
clientLogLevel: 'warning', // 日历级别
hot: true, // HMR
open: true, // 打开浏览器
contentBase: [path.join(__dirname, './dist'), 'public', path.join(__dirname, 'src/assets/')], // 获取静态资源
publicPath: '/',
compress: true, // 一切服务都启用gzip 压缩:
port: 9000
},
plugins: [
new webpack.HotModuleReplacementPlugin() // HMR
]
})
线上 webpack.prod.js
const { merge } = require('webpack-merge')
const commonConfig = require('./webpack.common')
const CopyWebpackPlgin = require('copy-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin') // 压缩CSS
// 合并公共配置
module.exports = merge(commonConfig, {
mode: 'production', // 开发模式
devtool: 'none', //没有源码
optimization: { // 优化
// useExports: true, // 没有使用的不会导出
minimize: true, // 压缩html
minimizer: [
new OptimizeCSSAssetsPlugin({}) // 压缩CSS
]
},
module: {
rules: [
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10*1024,
esModule: false,
name: 'img/[name].[hash:8].[ext]'
}
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000,
name: 'fonts/[name].[hash:8].[ext]'
}
}
}
]
},
plugins: [
new CleanWebpackPlugin(),
new CopyWebpackPlgin({
patterns: [
{ from: 'src/assets/', to: './assets'},
'public'
]
})
]
})
整理webpack.common.js
const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 插件 提取CSS, 压缩
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
// mode: 'development',
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'), // 输出文件路径, 必须使用绝对路径
filename: '[name][hash:8].js', // hash
},
// 配置通过别名来吧原导入路径映射成一个新的导入路径
resolve: {
// 导入语句没有携带文件后缀时, webpack会自动带上后缀后尝试访问文件是否存在
extensions: ['.js', '.vue', 'json'], //用于配置在尝试过程中用到的后缀列表
alias: { // 别名
components: path.join(__dirname, 'src/components')
}
},
module: {
rules: [
{
test: /\.less$/, // 处理less文件
use: [ // loader处理的顺序是从下到上
// 'style-loader' // 生成一个 style 标签,将 css-loader 处理后的字符串加载到界面中
MiniCssExtractPlugin.loader, // 将CSS提取到CSS文件中
'css-loader', // 将 css 代码处理为符合 commonjs 规范的代码,处理完成之后的内容是字符串
'less-loader' // 将 less 语法处理成 css 语法
]
},
{
test: /\.css/,
use: [
MiniCssExtractPlugin.loader, // 将CSS提取到CSS文件中
'css-loader', // 将 css 代码处理为符合 commonjs 规范的代码,处理完成之后的内容是字符串
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: [
// 下面的代码就好比是将我们当前配置中环境需要用到的 css处理语法加载进来
['postcss-preset-env']
]
}
}
}
]
},
{
test: /\.js$/, // js 处理(打包、校验、兼容、压缩)
loader: 'babel-loader',
exclude: /node_modules/, //node_modules 文件夹下的文件不处理
options: {
presets: [ // 预设 只是一个平台, 本身不处理
[
'@babel/preset-env', // 这个预设置只帮助我们完成一些基本的兼容 ,
{
useBuiltIns: 'usage', // usage 会根据配置的浏览器兼容,以及你代码中用到的 API 来进行 polyfill,实现了按需添加。
corejs: { version: 3 },
targets: { // 浏览器版本
chrome: '60',
firefox: '60',
ie: "9",
safari: '10',
edge: '17'
}
}
]
]
}
},
{
test: /\.(vue|js)$/, // js 处理(校验)
enforce: 'pre', // loader 先执行
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
fix: true // 解决问题的代码
}
},
{ // 处理字体
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
use: {
loader: 'url-loader',
options: {
limit: 10000
}
}
},
{ // 处理图片
test: /\.(png|gif|jpg)$/, // 处理图片
loader: 'url-loader',
options: {
esModule: false,
limit: 2 * 1024,
outputPath: 'img'
}
},
{
test: /\.vue$/,
exclude: /node_modules/,
loader: 'vue-loader'
}
]
},
plugins: [
new VueLoaderPlugin(),
new MiniCssExtractPlugin({
filename: 'css/[name].[hash:8].css', // 提取css文件中
}),
new HtmlWebpackPlugin({
template: './public/index.html',
publicPath: './', // 公共路径
}),
]
}