最早接触webpack时3.x,随着前端技术的发展,早已经不是之前,建一个
html
文件,里面引入js
,css
打开网页就可以看到效果静态页开发年代,现在的前段框架,vue
也好,react
也罢,都需要依赖于工具的支持,才能转换成浏览器可识别的语言,除此之外,webpack还做了例如代码压缩混淆,公共代码提取,autoprefixer,热更新等等一系列优化的功能,可见在现在这个发展趋势下,掌握webpack的配置,对前端来说是非常重要的,今天就来聊一聊webpack4.x。
安装:
1.npm install webpack webpack-cli -g
webpack-cli 是使用 webpack 的命令行工具,在 4.x 版本之后不再作为 webpack 的依赖了,我们使用时需要单独安装这个工具。
2.npm install webpack -D
作为项目中的依赖使用。
实验:
在package.json scripts
中加入build
命令:
"scripts": {
"build": "webpack --mode production"
}
新建src/index.js
, 随便写点js进去后在控制台执行npm run build
。
目录中会出先一个 dist
文件夹,打开里面的main.js
文件, 已经被混淆压缩过。
核心概念:
- entry 入口文件。
module.exports = {
entry: './src/index.js'
}
// 上述配置等同于
module.exports = {
entry: {
main: './src/index.js'
}
}
// 或者配置多个入口
module.exports = {
entry: {
foo: './src/page-foo.js',
bar: './src/page-bar.js',
// ...
}
}
- loader 文件转换器,例如把es6转换为es5,scss转换为css。
module: {
// ...
rules: [
{
test: /\.jsx?/, // 匹配文件路径的正则表达式,通常我们都是匹配文件类型后缀
include: [
path.resolve(__dirname, 'src') // 指定哪些路径下的文件需要经过 loader 处理
],
use: 'babel-loader', // 指定使用的 loader
},
],
}...
- plugin 插件,就可以理解为代码转换的工作都交给loader,打包构建的工作都交给plugin。
const UglifyPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
plugins: [
new UglifyPlugin()
],
}
- output,输出文件:
module.exports = {
// ...
output: {
//输出目录
path: path.resolve(__dirname, 'dist'),
//输出文件名
filename: 'bundle.js',
},
}
// 或者多个入口生成不同文件
module.exports = {
entry: {
foo: './src/foo.js',
bar: './src/bar.js',
},
output: {
filename: '[name].js',
//输出的文件名都按上面对应的key值来(foo, bar)
path: __dirname + '/dist',
},
}
// 路径中使用 hash,每次构建时会有一个不同 hash 值,避免发布新版本时线上使用浏览器缓存
module.exports = {
// ...
output: {
filename: '[name].js',
//如果文件没有改动,hash是不会变化的
path: __dirname + '/dist/[hash]',
},
}...
webpack 配置:
webpack 4.x 的一个核心买点就是 0 配置,所有配置都可以通过
package.json
类似如下的写法实现:
"scripts": {
"scripts": {
"dev": "webpack --mode development ./foo/src/js/index.js --output ./foo/main.js",
"build": "webpack --mode production ./foo/src/js/index.js --output ./foo/main.js"
}
}
但这种网上吐槽的声音比较多,而且很多实际需要的功能要么不支持,要么不知如何写,还是先建立wepack.config.js
,踏实一步步来吧!
把上面的几部分合在一起,就是一个简单的webpack
配置:
const path = require('path')
//压缩混淆代码
const UglifyPlugin = require('uglifyjs-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
module: {
rules: [
{
test: /\.jsx?/,
include: [
path.resolve(__dirname, 'src')
],
use: 'babel-loader',
},
],
},
// 代码模块路径解析的配置
resolve: {
//resolve.modules配置webpack去哪些目录下寻找第三方模块
modules: [
"node_modules",
path.resolve(__dirname, 'src')
],
/**
*在导入语句没带文件后缀时,
*webpack会自动带上后缀去尝试访问文件是否存在。
*resolve.extensions用于配置在尝试过程中用到的后缀列表,
*依次往后找。
*/
//
extensions: [".wasm", ".mjs", ".js", ".json", ".jsx"],
},
plugins: [
new UglifyPlugin()
],
}...
有了 webpack.config.js
控制台输入webpack
即可运行。
上述只是一个简单的 webpack.config.js 配置,但好像完全没有什么用 😂!
下面就来配置一个可以满足前端大概需求的webpack.config.js
:
前端打包一般需要达到的目的:
- 构建我们发布需要的 HTML、CSS、JS 文件
- 使用 CSS (sass,less)
- 处理和压缩图片
- 使用 Babel ES6 -》 ES5
- 本地起服务
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
module: {
rules: [
{
test: /\.jsx?/,
include: [
path.resolve(__dirname, 'src'),
],
use: 'babel-loader',
},
{
test: /\.less$/,
// 因为这个插件需要干涉模块转换的内容,所以需要使用它对应的 loader
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
'css-loader',
'less-loader',
],
}),
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader'
},
],
},
],
},
// 代码模块路径解析的配置
resolve: {
modules: [
"node_modules",
path.resolve(__dirname, 'src'),
],
extensions: [ ".js", ".json", ".jsx"],
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html', // 配置输出文件名和路径
template: 'src/index.html', // 配置文件模板
}),
new ExtractTextPlugin('[name].css'),
],
}
未完待续。。。
参考文件: