一、webpack介绍
webpack是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)
webpack可以将一些浏览器不能直接运行的拓展语言打包成适合浏览器可以使用的格式
功能:
- 代码转换
- 文件优化
- 代码分割
- 模块合并
- 自动刷新
- 代码校验
- 自动发布
二、环境安装与基本打包
(1)安装
yarn init -y
安装依赖
yarn add webpack webpack-cli -D
(2)不配置直接打包
当前目录下新建src然后添加一个文件index.js,写上内容,然后通过后面的命令打包
npx webpack
之后我们可以发现会生成dist/main.js
(3)手动配置
在node_module/webpack-cli/bin/config-yargs.js文件中有指定默认文件: webpack.config.js 或者webpackfile.js
let path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js', // 入口
output: {
filename: 'bundle.js', // 打包后的文件名
path: path.resolve(__dirname, 'build') // 必须是一个绝对路径
}
}
运行命令:
npx webpack
如果要自定义webpack配置文件,比如:webpack.config.my.js
npx webpack --config webpack.config.my.js
或者在package.json配置脚本:
"scripts": {
"build": "webpack --config webpack.config.my.js"
},
// 使用npm run build 执行
打包之后,将生成的js插入到html页面中,直接点击打开即可。
三、html插件
但是如果像上面那样手动打开,显得有点low,接下来我们可以
3.1 自动运行,在浏览器中打开
(1)下载webpack-dev-server
yarn add webpack-dev-server -D
(2)打包存在内存中
// webpack.config.js
module.exports = {
devServer: {
port: 3000, // 打开的端口
progress: true, // 是否显示进度条
contentBase: './build', // 指定运行的入口
open: true // 是否自动打开
},
}
// package.json
"scripts": {
"dev": "webpack-dev-server"
},
(3)执行
npm run dev
3.2 自动将打包成的插件引入到指定html中
(1)下载插件
yarn add html-webpack-plugin
(2)配置引入
let HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
...
plugins: [ // 放置所有webpack插件
new HtmlWebpackPlugin({
template: './src/index.html', // 模板(自定义预先生成一个html)
filename: 'index.html'
})
]
}
(3)执行
npm run build
之后我们可以发现会生成一个build目录,目录下有一个打包的bundle.js,还有一个index.html。
将mode改成production,则打包的js将会是压缩的,如果我们也想压缩html文件,则
output: {
filename: 'bundle.[hash:8].js', // 想要每次打包都不一样,hash值可取8位
path: path.resolve(__dirname, 'build') // 必须是一个绝对路径
},
plugins: [ // 放置所有webpack插件
new HtmlWebpackPlugin({
template: './src/index.html', // 模板
filename: 'index.html',
minify: {
removeAttributeQuotes: true, // 去掉双引号
collapseWhitespace: true, // 压缩成一行
},
hash: true //是否生成hash
})
]
// build/index.html
<script type=text/javascript src=bundle.1e8c2bb5.js?1e8c2bb50257bbdae710></script>
四、样式处理
4.1 css打包基本处理
css-loader
:解析@import这种语法
style-loader
: 把css插入到head标签中
loader
: 希望单一,只要一个字符串
loader执行顺序默认从右向左执行,那我们实际情况应该是先import,再插入标签
下载:
yarn add css-loader style-loader -D
// src/index.csss
@import './outer.css';
body {
background-color: yellow;
}
// out.css
body {
font-size: 18px;
}
// 第一种
module: {
rules: [
{ test: /\.css$/, use: ['style-loader', 'css-loader'] }
]
}
// 第二种
module: {
rules: [
{
test: /\.css$/, use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader'
}]
}
]
}
npm run build打包后npm run dev执行
使自定义的style生效
{
loader: 'style-loader',
options:
{
insert: 'top' //希望查到顶部,使原本的模板中的style放在后面可以生效
}
},
4.2 less打包处理
yarn add less less-loader -D
test: /\.less$/, use: [
{
loader: 'style-loader',
options: { insert: 'head' }
},
'css-loader',
'less-loader'
]
这两种都是把样式直接插入到head中,那么接下来我们就来介绍一种可以直接生成文件
4.3 使用css插件
yarn add mini-css-extract-plugin -D
在webpack.config.js中配置
// 引入,并设置打包的css输出文件名
let MiniCssExtractPlugin = require("mini-css-extract-plugin");
plugins: [
new MiniCssExtractPlugin({
filename: "main.css" //抽离出的css文件名
})
]
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader, //将style-loader替换掉,引入插件
{
loader: "css-loader"
}
]
}
]
}
如果我们要使用浏览器的前缀,则下载
yarn add postcss-loader autoprefixer -D
// index.less样式
body {
div {
color: #000;
transform: rotate(30deg);
}
}
//webpack.config.js 加入postcss-loader
module: {
rules: [
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"less-loader",
"postcss-loader" //在所有loader之前加入
]
}
]
}
//此时还要在根目录配置一个postcss.config.js,内容为:
module.exports = {
plugins: [require("autoprefixer")]
};
打包之后的main.css
body div {
color: #000;
-webkit-transform: rotate(30deg);
transform: rotate(30deg);
}
css压缩的方法:
yarn add optimize-css-assets-webpack-plugin -D
let OptimizeCSS = require("optimize-css-assets-webpack-plugin");
module.exports = {
optimization: {
//优化项
minimizer: [new OptimizeCSS()]
},
mode: 'production'
...
}
四、压缩js
yarn add uglifyjs-webpack-plugin -D
let UglifyJs = require("uglifyjs-webpack-plugin");
module.exports = {
optimization: {
//优化项
minimizer: [
new UglifyJs({
cache: true, // 是否缓存
parallel: true, // 是否是并发打包的
sourceMap: true // 源码映射
}),
new OptimizeCSS()
]
},
mode: 'production'
...
}
五、ES6转为ES5
5.1 我们看使用babel这个东西,可以帮我们将ES6转为ES5
yarn add babel-loader @babel/core @babel/preset-env -D
module: {
rules: [
{
test: /\.js$/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"] // 预设
}
}
},
...
}
// index.js中包含ES6语法
require("./index.css");
require("./index.less");
let out = require("./out");
console.log(out);
let fn = () => {
console.log("我在打印");
};
fn();
5.2允许使用装饰器
如果代码中包含ES7语法,则我们要安装
yarn add @babel/plugin-proposal-class-properties
babel-plugin-proposal-decorators
{ "plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose" : true }]
] }
yarn add @babel/plugin-proposal-decorators -D
module: {
rules: [
{
test: /\.js$/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"], // 预设
plugins: [
["@babel/plugin-proposal-decorators", { legacy: true }],
["@babel/plugin-proposal-class-properties", { loose: true }]
]
}
}
},
...
}
// src/index.js
let out = require("./out");
console.log(out);
let fn = () => {
console.log("我在打印");
};
fn();
@log
class A {
a = 1;
}
let obj = new A();
console.log(obj.a);
function log(target) {
console.log(target, 12);
}
打印结果:
i am outer
我在打印
ƒ A() {
_classCallCheck(this, A);
this.a = 1;
} 12
1
六、JS语法校验
6.1引入API
如果我们在js代码中运用了内置API,比如:
// outer.js
module.exports = "i am outer";
class B {}
function* gen(param) { // 内置API
yield 1;
yield 2;
}
console.log(gen().next());
这时候我们就需要代码运行包:
babel-plugin-transform-runtime官网
NOTE: Instance methods such as
"foobar".includes("foo")
will only work withcore-js@3
. If you need to polyfill them, you can directly import"core-js"
or use@babel/preset-env
'suseBuiltIns
option.
先安装包:
yarn add @babel/plugin-transform-runtime -D
6.2上线需要的安装
yarn add @babel/runtime -D
// src/index.js中使用了语法
"aaa".includes("a");
// 引入语法需要的
yarn add @babel/polyfill
引入前:
引入后:
6.3加入JS Eslint校验
yarn add eslint eslint-loader -D
下载设置完的eslintrc.json,并更改名字为.eslintrc.json
,然后添加到根目录
module: {
rules: [
// loader默认是从右向左,从下到上执行,设置enforce可以强制先执行这个校验
{
test: /\.js$/,
use: {
loader: "eslint-loader", // 使用eslint规范
options: {
enforce: "pre"
}
}
},
...
}