webpack简单使用
官网给出的的解释:本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。
webpack是基于nodejs的,所以语法遵循commonJs模块化规则
一个简单webpack配置通常包括以下几种属性:
momdule.exports = {
mode: '',
entry: {},
output: {},
devtool: '',
module: {},
plugins:{},
devServer: {},
resolve: {},
optimization: {}
}
下面是一些简单常用的配置属性:
entry
用来配置webpack打包的入口文件,webpack会根据entry指定的文件,查找依赖文件,进行打包,可以配置单入口或者多入口。
单入口配置:
const path = require('path');
module.exports = {
entry: path.resolve(__dirname, '../src/index.js')
}
默认entry会打包src下面的index.js文件,打包到dist文件夹生成一个main.js
上面代码用到一个node中自带的变量__dirname,是指当前文件所在的文件夹的绝对路径。
这里默认配置文件和入口主文件在项目中的位置:
假如该配置文件的路径是在/Users/chensir/project/myapp/config/webpack.config.js
那么__dirname输出的就是:
/Users/chensir/project/myapp/config
另外还有一个变量 __filename,是指当前文件所在的绝对路径,输出的是:
/Users/chensir/project/myapp/config/webpack.config.js
可以使用字符串直接拼接成一个完整的路径,去在webpack配置中使用,例如:
const file = __dirname + "/index.html"
如果需要的文件或者文件路径在该文件的外层,需要使用node中自带的核心模块==path==,作用是拼装转换路径生成一个绝对路径:
const path = require('path');
let filePath = path.resolve(__dirname, '../src/index.js')
filePath输出的就是: /Users/chensir/project/myapp/src/index.js
output
出口配置
output属性可以配置webpack打包之后,输出的文件目录以及文件的名称。默认情况,配置文件和src文件夹位置同级,主入口文件经过打包之后,会默认出入到./dist/main.js,其他文件默认输入到./dist文件夹下。
这里默认配置文件和入口主文件在项目中的位置:
简单的一个出口配置:
module.exports = {
entry: path.resolve(__dirname, '../src/index.js')
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'bundle.js'
}
}
output 属性告诉 webpack 在哪里输出它所打包后的文件,以及如何命名这些文件。
常见的output配置:
module.exports = {
entry: path.resolve(__dirname, '../src/index.js')
output: {
path: path.resolve(__dirname, '..', 'dist'),
filename: 'js/[name].[hash:8].js',
chunkfilename:
publicPath:
clean: true // webpack 5.20.0+版本支持,不需要在使用clean-webpack-plugin
}
}
主要参数:
- path: 打包后的js文件输出到哪里,一个绝对路径。只影响js文件的位置,css和图,在他们各自的配置中
- filename: 打包后的文件名称,可以写额外的文件夹地址: 'static/js/[name].js'
- chunkFilename: 非主入口文件打包后的文件名称,例如:import() 异步导入的文件
- publicPath: 加载静态资源时的前缀
==一般配置路径相关参数时,publicPath以/结尾,loader中配置path和filename涉及路径时,不用以/开头==
还有两个比较重要的配置: library、libraryTarget,新版webpack将要弃用libraryTarget,改为在library.type配置:
- library: 用来设置主入口导出赋值给什么变量
- libraryTarget: 设置以什么方式导出
entry和output共同配置多入口文件:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
let mainname = 'my-main'
module.exports = {
entry: {
index: path.resolve(__dirname, '../src/index.js'),
home: path.resolve(__dirname, '../src/home.js'),
[mainname]: path.resolve(__dirname, '../src/main.js')
},
output: {
path: path.resolve(__dirname, '../dist'),
filename: 'static/js/[name].js'
},
plugins: [
new HtmlWebpackPlugin({
template: __dirname + "/index.html",
filename: 'index.html',
chunks: ['index']
}),
new HtmlWebpackPlugin({
template: __dirname + "/index.html",
filename: 'home.html',
chunks: ['home', 'my-main']
})
]
}
entry中可以使用[]去使用变量当做名字。配置output的filename时,可以使用占位符[name],会直接使用entry中配置的入口文件的名字,还有其他的占位符,如: [hash:8] [ext]。
module
webpack只会识别符合规范的普通js文件、json文件,像es6新语法, jsx、vue,css,图片等文件,都需要使用特殊的loader,去解析转换。在module模块中配置rules,webpack会根据规则,当识别特定的文件时,交给对应的loader去解析。
loader实际就是一个函数,会引入文件在内部进行解析转化后输出
module.exports = (file) => {
.....
return xxxxx
}
一个简单的loader使用:
const path = require('path');
module.exports = {
output: {
filename: 'my-first-webpack.bundle.js',
},
module: {
rules: [{ test: /\.txt$/, use: 'raw-loader' }],
},
};
当碰到==在 require()/import 语句中被解析为 '.txt' 的路径时==,在打包之前,webpack会先使用raw-loader 转换一下。
在webpack配置中loader两个属性
- test属性,匹配哪些文件需要使用loader转换
- use属性,匹配到的文件使用那种loader准换。可以直接传入loader名称,如果loader需要一些配置,像babel-loader,可以传入一个对象。如果需要使用多个loader,需要传递一个数组。注意:==当多个loader时,是从数组的最后一个loader以此向前解析。==
常见的需要loader处理的文件:
css、scss、less等处理样式的文件:
在webpack中,直接使用import 或者 requore引入css文件是不支持的,需要使用css-loader去处理css文件,css-loader会将css文件引入,解析转换文件还需要其他的loader和插件处理。
在webpack中引入的css文件或者(scss、less,还需要其他loader)等css预处理文件,最终可以生产两种格式。
- 最直接的转成style标签插入到html中,将css文件中的样式写入style标签中,最后插入的html中
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
}
需要先使用css-loader识别引入css文件,在利用style-loader将生成的style标签插入到html中。
使用style标签插入的方式,配置起来是简单的,但是一个完整的项目,会有众多css文件,将全部的css文件一下插入页面中,加载是会阻塞js的执行,这样页面加载时间会很长,所以还有另外的一种方式:
- 把css文件生成单独的css文件,使用link引入
需要安装mini-css-extract-plugin插件,这个插件会提供一个loader,并且需要配置插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
plugins: [
new MiniCssExtractPlugin({
name: 'css/[name].[ext]',
chunkFilename: "css/[id].css"
})
]
}
MiniCssExtractPlugin解析后,会将所有的文件生成一个css文件,后面优化会处理拆分css文件
scss、和less这些css预处理器文件,还需要对应的loader去处理
scss 需要使用sass-loader,less需要使用less-loader。还需要配置一些指定的options。例如配置source map
module.exports = {
module: {
rules: [
{
test: /\.less$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'less-loader',
options: {
sourceMap: true,
},
},
],
},
],
},
};
js jsx ts tsx文件:
webpack打包时,只能识别符合规范的es5语法,如果要解析转换es6语法,需要用到一些特定的loader去处理。
简单的处理js文件的loader的配置:
module.export = {
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-react',
'@babel/preset-env'
],
plugins: []
}
}
}
]
}
}
bable用于代码的转译,将打包之前的代码转换成符合预期规范的代码。在转译的 过程中,babel 内部经历了「==解析 - 转换 - 生成==」三个步骤
babel-loader负责将js、ts等文件引入。@babel/core是babel的核心模块,内部有对代码进行转换的核心方法,至于转换成什么需要用到==preset==(预设)和==plugin==(插件)来处理。可以直接配置在webpack中,也可以单独创建一个++++++babel++++.config.js++文件配置,在babel解析转换时,会按照本地的配置来。
babel是基于插件化的,想一些特定的语法需要特定的babel插件里,如果不配置,那输入和输出就是一样的,无法解析
常见的preset
- @babel/preset-env
- @babel/preset-react
- @babel.preset-typescript
babel参考文章:www.cnblogs.com/bai1218/p/1…
ts、tsx文件想要校验还需其他配置:
babel提供了处理ts文件的预设,@babel/preset-typescript。 还需要安装typescript,去初始化一个ts.config.js,校验ts类型文件,并且提供提示,一些依赖提示需要安装官方提供的ts类型文件,如react需要安装@types/react,这样才能检验和提示功能。
png jpg svg 以及woff字体图标文件:
像图片之类的文件,需要使用url-loader和file-loader处理:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|jpeg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
name: 'static/images/[name].[hash:8].[ext]',
limit: 10 * 1024
}
}
]
}
]
}
}
图片较小时,可以使用url-loader处理成base64格式直接引入,减少页面的http请求,同时对于较大的图片,可以设置limit,如果大于限制,file-loader会处理成单独的图片文件,打包到指定文件夹。
在 webpack5 中,asset modules 替换了上述的 loader,添加了 4 中内置类型:
- asset/resource 之前由 file-loader 实现
- asset/inline 之前由 url-loader 实现
- asset/source 导出资源的源码(字符串类型),之前由 raw-loader 实现
- asset 可以自动选择导出为 data URI 还是直接发送文件,之前由 url-loader 实现。