在了解如何配置Webpack之前,我们应该先知道Webpack是干什么的,以及我们为什么要配置webpack。
首先关于webpack是干什么的
webpack 是一个模块打包器。它的主要目标是将 JavaScript 文件打包在一起,打包后的文件用于在浏览器中使用,但它也能够胜任转换(transform)、打包(bundle)或包裹(package)任何资源(resource or asset)。
从这段话中我们可以了解到Webpack中有三大特性,转换,打包,包裹任何资源。之后我会一一为大家讲解
在开发web应用时,假如我们没有任何构建工具,会出现那些问题呢?
1.浏览器运行速度缓慢
在我们实际开发中会引入很多的库,当浏览器加载过多的库时,就会导致浏览器响应很慢。
2.浏览器无法理解代码
当我们使用es6,es7或者ts进行开发时,我们会发现浏览器解析不了我们开发的代码,所以我们需要工具来将我们的代码转化成浏览器能识别的语言
在现在的开发中,打包工具的构建已经是必不可少的一部分
现在我们就来了解如何配置Webpack
entry指示应使用哪个模块 webpack 开始构建其内部依赖关系图。Webpack将找出入口点依赖的其他模块和库(直接和间接)。
官网地址
用法:entry: string | [string]
一个webpack工程,首先至少要有一个入口。
module.exports = {
entry: './index.js'
};
module.exports = {
entry: {
main: './path/to/my/entry/file.js',
},
};
两种写法都可以
也可以有多个入口:
module.exports = {
entry: {
pageA: './pageA.js',
pageB: './pageB.js'
}
};
module.exports = {
entry: ['./pageA.js', './pageB.js']
};
这样配置后会将多个js文件,最终打包成一个入口。
output属性告诉 webpack 在何处发出它创建的捆绑包以及如何命名这些文件。它默认为主输出文件和任何其他生成的文件的文件夹
最基本的配置为:
module.exports = {
output: {
filename: 'output.js', // 文件名
}
};
如果您的配置创建了多个“块”(例如多个入口点或使用CommonsChunkPlugin等插件),则应使用变量来确保每个文件具有唯一的名称。
module.exports = {
entry: {
pageA: './indexA.js',
pageB: './indexB.js'
},
output: {
filename: '[name].js',
path: __dirname + '/dist',
}
};
在开发中,当我们需要访问服务器资源的地址时,我们需要配置publicPath
module.exports = {
output: {
publicPath: '/static/web/',
path: path.resolve(__dirname, "../dist"),
filename: '[name]_[chunkhash].js',
},
};
path:用来存放打包后文件的输出目录
publicPath:指定资源文件引用的目录
在实际开发中,publicPath是运维为我们配置的前端资源存放的地址,当我们配上publicPath地址后,我们的访问地址就需要带上publicPath
例:https://www.baidu.com/static/web/login
output还有很多其他属性,具体可以查看官网
正如最上面的的一段引用中所描述,我们需要Webpack来进行代码的转换(transform)。
Webpack不仅仅能处理js文件,还能处理css、图片。而且也能将ES6的代码、TypeScript的代码转换为浏览器可执行的代码。
不同的文件需要不同的loader来进行转换,如babel-loader,css-loader,less-loader,scss-loader等
这些转换操作都是在module中进行的,如将es6转化为es5:
module.exports = {
//...
module: {
rules: [
{
test: /\.(js)$/,
use: 'babel-loader'
}
]
}
};
上面的代码是转化我们项目中所有的资源,但当我们引入的一些第三方库中已经转化过,我们是不需要对他进行转化的。这时我们就需要排除指定库的转化:
module.exports = {
//...
module: {
rules: [
{
test: /(\.jsx|\.js)$/,
exclude: /(node_modules|bower_components)/,
use: ['happypack/loader']
},
{
test: /(\.jsx|\.js)$/,
include: [path.resolve('node_modules/react-sortablejs')],
use: ['babel-loader', 'happypack/loader',],
},
]
}
};
exclude:过滤指定的库
include:匹配指定的库
在此列举一些常用的转换:
module: {
rules: [
//less样式转css
{
test: /(\.css|\.less)$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'less-loader']
})
},
//svg图片格式转化
{
test: /\.svg$/,
issuer: { test: /\.(js|ts|jsx|tsx)x?$/ },
use: ['@svgr/webpack']
},
//其他语法转es5
{
test: /(\.jsx|\.js)$/,
exclude: /(node_modules|bower_components)/,
use: ['happypack/loader']
},
{
test: /(\.jsx|\.js)$/,
include: [path.resolve('node_modules/react-sortablejs')],
use: ['babel-loader', 'happypack/loader',],
},
//sass样式转css
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ["css-loader", "sass-loader"]
})
},
//图片转化
{
test: /\.(png|svg|jpg|gif|xlsx|pdf)$/,
use: "url-loader?limit=1024&name=[name].[ext]&outputPath=img/"
},
]
},
resolve就是去解析配置的模块。通俗来讲就是为模块起别名。
该配置为非必须,你也可以不用配置它
例如:
module.exports = {
//...
resolve: {
alias: {
'@container': path.resolve(__dirname, "../src/container"),
}
}
};
这样在某些需要相对路径比较深的模块引入时,可以从这样:
import container from ‘…/…/…/src/container’
变为这样:
import container from ‘@container’
loader 被用于转换某些类型的模块,而plugin则可以用于执行范围更广的任务。plugin的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。plugin接口功能极其强大,可以用来处理各种各样的任务。
想要使用一个plugin,你只需要 require() 它,然后把它添加到 plugins 数组中。多数plugin可以通过选项(option)自定义。你也可以在一个配置文件中因为不同目的而多次使用同一个plugin,这时需要通过使用 new 操作符来创建它的一个实例。
使用方法:
plugins: [
new HtmlWebpackPlugin({
filename: "index.html",
template: "./src/index.ejs",
favicon: "favicon.ico",
chunks: ["vendors", "index"]
}),
]
当有多个出口文件时,我们就需要配置多个plugins
plugins: [
new HtmlWebpackPlugin({
filename: "indexA.html",
template: "./src/indexA.ejs",
favicon: "favicon.ico",
}),
new HtmlWebpackPlugin({
filename: "indexB.html",
template: "./src/indexB.ejs",
favicon: "favicon.ico",
}),
]
html-webpack-plugin中还有很多属性,具体可看github文档
需要了解plugins中还有那些插件,可以查看官方文档
还有一个比较重要的插件uglifyjs-webpack-plugin,使用该插件可对代码进行压缩、混淆。
使用方法:
plugins: [
new UglifyJSPlugin({
exclude: /node_modules/,
parallel: true,
uglifyOptions: {
compress: {//其他压缩选项
arguments: false,
drop_console: true, // 控制删除打印
keep_infinity: true,
top_retain: true,
},
output: {//其他输出选项(默认值已针对最佳压缩进行了优化)
beautify: false,
keep_quoted_props: true,
wrap_iife: true,
},
ie8: true,//启用 IE8 支持
mangle: false,//启用名称修改
sourceMap: false// 如果要指定源映射选项,请传递对象
}
}),
]
uglifyjs-webpack-plugin常用的属性
test:测试匹配的文件
exclude:排除的文件
include:包含的文件
parallel:使用多进程并行运行和文件缓存来提高构建速度
uglifyOptions:压缩,混淆,优化代码的属性
至此我们已经大致了解了Webpack如何配置,以及配置Webpack的好处。
但是我们如何在本地运行我们的项目,以及在开发中如何热更新我们的代码呢?
通过上面的问题,我们就引出了devServer。
通过配置了devServer,我们就能在本地访问我们的测试服务器
下面我们就来看看devServer如何配置,以及他有那些常用属性
module.exports = {
devServer: {
contentBase: path.resolve(__dirname, '../dist'),
disableHostCheck:true,
hot: false,
hotOnly: false,
host: "0.0.0.0",
port: 8081,
historyApiFallback: true,
stats: "errors-only",
proxy: [
{
context: [''],//模块名
target: 'www.baidu.com',//服务器域名地址
changeOrigin: true,
secure: true,//验证 SSL 证书
}
]
}
}
contentBase:告诉服务器从哪里获取资源
disableHostCheck: 设置为 true 时,此选项将绕过主机检查。就是通常我们所说的跨域。
hot:启用 webpack 的模块热替换。当你启用后,webpack会自动帮你添加一个热更新插件,如没有插件是无法进行热更新的
hotOnly:启用热模块替换,无需页面刷新更新.
host:指定使用一个 可以访问静态资源的地址
默认可通过localhost域名访问,如需要通过配置的测试服务器地址访问则设置为0.0.0.0
例如:我如果设置为0.0.0.0,
那么我可以通过proxy属性中target设置的路径访问:www.baidu.com:8081。同域名下所有人都可访问到该地址
如果未设置,则只能通过localhost或者127.0.0.1访问
port:服务端口号。不配置时,默认为8080
historyApiFallback:当匹配的配置文件不存在时,不出现404
proxy:配置后端开发服务器 API,并且在同域名下发送 API 请求
至此,我们的Webpack基础配置已经讲解完成。后面会持续更新正式开发中如何配置,以及我们如何暴露我们自己的工具库来进行使用
如需转载,请注明出处
引用:
https://www.yuque.com/fe9/basic/fnvdeu#zph7uv
https://www.webpackjs.com/concepts/