手把手教你webpack常用配置

237 阅读2分钟

webpack本身是基于node.js开发的。

学习网址:webpack.docschina.org/

1. 安装webpack

目前vue/clicreate-react-app基本上采用的是webpack4.0以上版本,第四代版本需要我们安装webpackwebpack-cli(可执行命令);

为了防止全局安装webpack的版本冲突,我们真实项目开发的时候基本上以安装在本地项目中为主;

$ npm init -y

$ npm install webpack webpack-cli --save-dev
OR
$ yarn add webpack webpack-cli -D

2.webpack的基础使用

  • 初步体验(零配置)
/*
 * 默认会打包SRC目录中的JS文件(入口默认index.js)
 * 打包完成的目录默认是DIST/MAIN.JS
 *
 * npx:http://www.ruanyifeng.com/blog/2019/02/npx.html
 * 默认执行node_modules/bin/webpack.cmd文件
 * webpack默认支持CommonJS和ES6 Module的模块规范,依此进行依赖打包
 
    + ES6 Module的引入导出 import export
        +只能在第一行导入
    + commonJS的引入导出 require module.export
 */
$ npx webpack
  • 自定义基础配置

(一般写webpack.config.js OR webpackfile.js,在此文件配置)

let path = require('path');
module.exports = {
	//=>打包模式  开发环境development  生产环境production(压缩)
	mode: 'production',
	//=>入口
	entry: './src/index.js',
	//=>输出
	output: {
		//=>输出文件的文件名('bundle.[hash].js')
		filename: 'bundle.js',
		//=>输出目录的"绝对路径"
		path: path.resolve(__dirname, 'dist')
	}
}
  • 自定义配置文件名
    • $ npx webpack --config webpack.config.development.js
    • 可在package.json中配置可执行的脚本命令(区分开发环境)
"scripts": {
    "serve": "webpack --config webpack.config.development.js",
    "build": "webpack --config webpack.config.production.js"
},

3.webpack-dev-server(实现类似live server)

webpack.js.org/configurati…

  • 安装:$ yarn add webpack-dev-server -D
  • 基础配置
/* webpack.config.js */
//=>配置DEV-SERVER
devServer: {
    //=>端口
	port: 3000,
    //=>显示编译进度
    progress: true,
    //=>指定访问资源目录
    contentBase: './dist',
    //=>自动打开浏览器
    open: true
}
/* package.json */
"scripts": {
    "serve": "webpack-dev-server",
    "build": "webpack"
}
  • $ npm run serve
  • $ npx webpack-dev-server 代码更改后,会自动重新编译,然后自动刷新页面

4.html-webpack-plugin(处理HTML)

www.webpackjs.com/plugins/htm…

  • 安装:$ yarn add html-webpack-plugin -D
  • 在webpack.config.js中使用
let HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    ...,
    //=>在webpack中使用插件
	plugins: [
		new HtmlWebpackPlugin({
			//=>指定自己的模板
			template: './src/index.html',
			//=>输出的文件名
			filename: 'index.html',
			//=>给引入的文件设置HASH戳(清除缓存的),也可以在output中设置 filename: 'bundle.[hash].js' 来生成不同的文件
			hash: true,
			//=>控制是否以及以何种方式最小化输出 	//=>https://github.com/kangax/html-minifier
			minify: {
				collapseWhitespace: true,
				removeComments: true,
				removeAttributeQuotes: true,
				removeEmptyAttributes: true
			}
		})
	]
}

5.webpack中的加载器loader:处理样式的

  • 安装:$ yarn add css-loader style-loader less less-loader autoprefixer postcss-loader ... -D
  • 使用
module.exports = {
    //=>配置模块加载器LOADER
	module: {
		//=>模块规则:使用加载器(默认从右向左执行,从下向上)
		rules: [{
			test: /\.(css|less)$/, //=>基于正则表达式匹配哪些模块需要处理
			use: [
				"style-loader", //=>把CSS插入到HEAD中(内嵌式)【但是需要在index.js中单独引入CSS[require['./xxx.css']】
				"css-loader", //=>编译解析@import/URL()这种语法
                "postcss-loader", //=>设置前缀
                {
					loader: "less-loader",
                    options: {
                        //=>加载器额外的配置
                    }
				}
			]
		}]
	}
}

需新建postcss.config.js

module.exports = {
	plugins: [
		require('autoprefixer')
	]
};

package.json

"browserslist": [
    "> 1%",
    "last 2 versions"
]

6.mini-css-extract-plugin 抽离CSS内容

www.npmjs.com/package/min…

  • 安装 $ yarn add mini-css-extract-plugin optimize-css-assets-webpack-plugin uglifyjs-webpack-plugin -D
let MiniCssExtractPlugin = require('mini-css-extract-plugin'),
	OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin'),
	UglifyjsWebpackPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
    //=>设置优化项
	optimization: {
		//=>设置压缩方式
		minimizer: [
			//=>压缩CSS(但是必须指定JS的压缩方式)
			new OptimizeCssAssetsWebpackPlugin(),
			//=>压缩JS
			new UglifyjsWebpackPlugin({
				cache: true, //=>是否使用缓存
				parallel: true, //=>是否是并发编译
				sourceMap: true, //=>启动源码映射(方便调试)
			})
		]
	},
	plugins: [
		//=>使用插件
		new MiniCssExtractPlugin({
			//=>设置编译后的文件名字
			filename: 'main.css'
		})
	],
	module: {
		rules: [{
			test: /\.(css|less)$/,
			use: [
				// "style-loader",
				//=>使用插件中的LOADER代替STYLE方式
				MiniCssExtractPlugin.loader,
				"css-loader",
                "postcss-loader",
				"less-loader"
			]
		}]
	}
}

7.基于babel实现ES6的转换和ESLint语法检测

babeljs.io/

eslint.org/

  • 安装 $ yarn add babel-loader @babel/core @babel/preset-env @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators @babel/plugin-transform-runtime -D
  • 安装 $ yarn add @babel/runtime @babel/polyfill
  • 安装 $ yarn add eslint eslint-loader -D【检测语法规范】
module.exports = {
	...,
	module: {
		rules: [...,{
			test: /\.js$/,
			use: [{
				loader: 'babel-loader',
				options: {
					//=>转换的语法预设(ES6->ES5)
					presets: [
						"@babel/preset-env"
					],
					//=>基于插件处理ES6/ES7中CLASS的特殊语法
					plugins: [
						["@babel/plugin-proposal-decorators", {
							"legacy": true
						}],
						["@babel/plugin-proposal-class-properties", {
							"loose": true
						}],
						"@babel/plugin-transform-runtime"
					]
				}
			}], //=>, "eslint-loader"
			//=>设置编译时忽略的文件和指定编译目录
			include: path.resolve(__dirname, 'src'),
			exclude: /node_modules/
		}]
	}
}

参考https://eslint.org/demo生成 .eslintrc.json

补充知识:在vscode中开启ES7中类的装饰器,项目根目录中设置 jsconfig.json

{
	"compilerOptions": {
		"experimentalDecorators": true
	}
}
@log
class A{
	a=1;
}

8.暴露全局loader

  • $ yarn add expose-loader -D
  • 前置加载器、后置加载器、普通加载器...
//=>内联加载器
import jquery from 'expose-loader?$!jquery';
console.log(window.$);

{
    //=>只要引入JQUERY就在全局注入$
    test: require.resolve('jquery'),
    use: ['expose-loader?$']
}
let webpack = require('webpack');
module.exports = {
    plugins: [
		//=>在每个模块中都注入$
		new webpack.ProvidePlugin({
			'$': 'jquery'
		})
	],
}

//=>页面中
console.log($);

9.webpack中图片的处理和分目录分发

  • 在JS中创建IMG
  • 在CSS中设置背景图
  • 在HTML中写死
  • ...

安装 $ yarn add file-loader url-loader html-withimg-loader -D

module.exports = {
	...,
	module: {
		//=>模块规则:使用加载器(默认从右向左执行)
		rules: [..., {
			test: /\.(png|jpg|gif|ico|webp|bmp)$/i,
			use: [{
				//=>把指定大小内的图片BASE64
				loader: 'url-loader',
				options: {
					limit: 200 * 1024,
    				outputPath:'/images'
				}
			}],
			include: path.resolve(__dirname, 'src'),
			exclude: /node_modules/
		}, {
			test: /\.(html|htm|xml)$/,
			use: ['html-withimg-loader']
		}]
	}
}

最后实现文件分目录发布

module.exports = {
	output: {
		//=>配置引用前缀(所有资源前加这个地址)
		publicPath: './'
	},
	plugins: [
		new MiniCssExtractPlugin({
			filename: 'css/main.css'
		})
	],
	module: {
		//=>模块规则:使用加载器(默认从右向左执行)
		rules: [...,{
			test: /\.(png|jpg|gif)$/i,
			use: [{
				options: {
					outputPath: 'images'
				}
			}]
		}]
	}
}