写给自己看的webpack入门配置
/ / 点击 / 阅读耗时 15 分钟如果想要成为一名优秀的前端开发人员,除了对基础编程语言的掌握以外。项目工程化也是需要了解和掌握的,目前大部分开发人员使用webpack作为项目构建工具。而我对于webpack的了解不是很多。正好趁这段时间学习一下webpack的基础及配置。
webpack核心概念
webpack作为一个现代 JavaScript 应用程序的静态模块打包器有以下几个核心概念:
- 入口(entry)
- 输出(output)
- loader
- 插件(plugins)
入口(entry)
入口(entry)一般是webpack指定哪个模块(文件)作为构建内部依赖的开始。从入口文件开始,webpack会找出哪些模块和库是入口文件依赖的,每个依赖被处理最后将输出到 bundles 的文件中。
// webpack.config.js
module.exports = {
entry: './path/to/my/entry/file.js'
};
出口(output)
出口(output)是作为webpack通过编译输出的目录名称,主要是用来接收处理后文件保存的位置,默认值为’./dist’。
const path = require('path');
module.exports = {
entry: './path/to/my/entry/file.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
}
};
loader
loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块。
const path = require('path');
module.exports = {
output: {
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
}
};
以上配置对一个module定义了rules属性,里面包含两个必须属性:test和use。这相当于告诉webpack:
“嘿,webpack 编译器,当你碰到「在 require()/import 语句中被解析为 ‘.txt’ 的路径」时,在你对它打包之前,先使用 raw-loader 转换一下。”
插件(plugin)
上面讲到loader被用于转换某些类型的模块(如转换.vue、.jpeg、.jsx)等。而插件(plugin)可以处理更广的任务,从打包优化和压缩,一直到重新定义环境中的变量。
插件使用的方法一般是通过require引入,然后将其添加到plugin数组中。
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
const webpack = require('webpack'); // 用于访问内置插件
const config = {
module: {
rules: [
{ test: /\.txt$/, use: 'raw-loader' }
]
},
plugins: [
new HtmlWebpackPlugin({template: './src/index.html'})
]
}
从0开始我们的配置
1.1 初始化项目
新建一个目录,初始化npm
npm i
安装webpack包
npm i -D webpack webpack-cli
新建一个 src 文件,然后创建一个main.js,然后写点测试代码
console.log('hello world');
配置package.json命令
"scripts": {
"build":"webpack src/main.js"
}
如果生成了dist目录,就说明内部含有main.js文件打包成功了
1.2 开始自己的配置
以上只是webpack默认配置,如果想要实现更灵活丰富的配置还需要自己动手进行自定义配置。首先新建build文件夹,里面新建一个webpack.config.js文件。
//webpack.config.js
const path = require('path');
module.exports = {
mode:'development', // 开发模式
entry: path.resolve(__dirname,'../src/main.js'), // 入口文件
output: {
filename: 'output.js', // 打包后的文件名称
path: path.resolve(__dirname,'../dist') // 打包后的目录
}
}
然后更改下打包命令
"scripts": {
"build":"webpack --config build/webpack.config.js"
},
执行 npm run build 就在dist目录下生成了 output.js 文件,这个文件就是我们需要在浏览器中实际运行的文件。
1.3配置HTML模板
以上JS打包好后,需要引入到HTML文件中,但是不可能每次都要手动引入。且为了考虑服务器缓存优化,每次更新后的js文件名称需要动态改变。基于这两点,我们开始自定义配置:
为了服务器缓存,首先改变每次输出js文件名称
module.exports = {
output: {
filename: '[name].[hash:8].js', //打包后生产唯一8位的hash值
path:path.resolve(__dirname,'../dist') //打包后的目录
}
}
接下来新建一个public文件夹,里面新建index.html文件,然后需要借助一个插件:
npm i -D html-webpack-plugin
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, '../src/main.js'), //入口文件
output: {
filename: '[name].[hash:8].js', //打包后的文件名称
path:path.resolve(__dirname,'../dist') //打包后的文件夹
},
plugins: [
new HtmlWebpackPlugin(
{
template:path.resolve(__dirname,'../public/index.html') //HTML模板文件
}
)
]
}
此时执行 npm run build 会发现 dist 目录下会出现index.html,并且html文件动态引入最新生成的js文件。
1.3.1 clean-webpack-plugin
由于我们每次执行npm run build 会发现dist文件夹里会残留上次打包的文件,这里推荐一个plugin来帮我们在打包输出前清空文件夹clean-webpack-plugin
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
module.exports = {
// ...省略其他配置
plugins:[new CleanWebpackPlugin()]
}
1.4引用CSS
首先在我们的入口文件 main.js 中引入css文件,引入css文件后需要配置css-loader来解析
//main.js
import './assets/index.css'
import './assets/test.css'
npm i -D style-loader css-loader
如果是less来构建则多需要安装两个loader
npm i -D less less-loader
配置文件如下:
// webpack.config.js
module.exports = {
// ...省略其他配置
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader'] // 从右向左解析原则
},
{
test:/\.less$/,
use:['style-loader','css-loader','less-loader'] // 从右向左解析原则
}
]
}
}
执行命令后会重新打包,打开HTML后会发现css已经起作用了,但是打开控制台发现样式是嵌入式。
为了解决以上问题,我们可以使用官方推荐的 ExtractTextWebpackPlugin 插件来解决这个问题
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin')
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, '../src/main.js'),
output: {
filename: '[name].[hash:8].js',
path: path.resolve(__dirname, '../dist')
},
plugins: [
new HtmlWebpackPlugin(
{
template: path.resolve(__dirname, '../public/index.html')
}
),
new CleanWebpackPlugin(),
new ExtractTextWebpackPlugin({
filename:'css/[name][hash:8].css'
}),
],
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextWebpackPlugin.extract({
use: ['css-loader']
})
},
]
}
}
1.5加载图片等媒体文件
file-loader 和 url-loader 可以接收并加载任何文件,然后将其输出到构建目录。url-loader 一般与 file-loader 搭配使用,功能与 file-loader 类似,不过 url-loader 可以配置存储文件上限,如果超出配置的大小则会返回base编码。
module.exports = {
//...省略其他配置
{
test: /\.(jpe?g|png|gif)$/i, //T图片文件
use: [
{
loader: 'url-loader',
options: {
limit: 10240,
fallback: {
loader: 'file-loader',
options: {
name: '[name].[hash:8].[ext]',
outputPath: 'images/' //打包后的文件目录
}
}
}
}
]
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, //媒体文件
use: [
{
loader: 'url-loader',
options: {
limit: 10240,
fallback: {
loader: 'file-loader',
options: {
name: '[name].[hash:8].[ext]',
outputPath: 'media/' //打包后的文件目录
}
}
}
}
]
}
}
1.6css引入图片资源导致的Bug
在我按照以上配置完成执行 npm run build 成功执行编译,但是执行打包后的HTML文件却不能正常显示背景图片,具体原因通过查看编译后的文件发现,造成bug的原因是css背景图片路径出现了问题。
webpack在打包后,css引入的资源路径是按照绝对路径引入的。这就当前css文件夹下的css文件引入资源失效。
解决css引入资源失效问题也非常好解决,就是在 css-loader 配置里面添加一个配置项:
module.exports = {
//...省略其他配置
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextWebpackPlugin.extract({
use: ['css-loader'],
publicPath: '../' //publicPath会输出解析文件目录
})
},
]
}
}
1.7用babel转义js文件
首先安装babel-loader
npm i -D babel-loader @babel/preset-env @babel/core
具体配置如下
module.exports = {
//...省略其他配置
module: {
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
}
}
1.8构建Vue开发环境
npm i -D vue-loader vue-template-compiler vue-style-loader
npm i -S vue
vue-loader 用于解析 .vue 后缀文件
vue-template-compiler 用于编译模板
const vueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
module:{
rules:[{
test:/\.vue$/,
use:['vue-loader']
},]
},
resolve:{
alias:{
'vue$':'vue/dist/vue.runtime.esm.js',
' @':path.resolve(__dirname,'../src')
},
extensions:['*','.js','.json','.vue']
},
plugins:[
new vueLoaderPlugin()
]
}
按照以上配置完成后,接下来在 main.js 文件中导入Vue:
import Vue from 'vue'
import App from './app'
new Vue({
render: h => h(App)
}).$mount('#app')
public文件夹下面的index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ExampleWebpack</title>
</head>
<body>
<div id="app"></div>
</body>
</html>
然后再Src文件夹下新建App.vue
<template>
<div class="div">{{msg}}</div>
</template>
<script>
export default {
data(){
return {
msg:'hello Vue'
}
}
};
</script>
<style>
.div{
color:red;
display: flex;
font-size: 24px;
}
</style>
以上已完成了Vue项目的搭建,为了让项目更接近开发模式,引入 webpack-dev-server 热更新来辅助我们。
1.8.1 引入webpack-dev-server
npm i -D webpack-dev-server
const Webpack = require('webpack')
module.exports = {
// ...省略其他配置
devServer:{
port:3000,
hot:true,
contentBase:'../dist'
},
plugins:[
new Webpack.HotModuleReplacementPlugin()
]
}
1.9配置打包命令
"scripts": {
"dev": "webpack-dev-server --config build/webpack.config.js --open",
"build": "webpack --config build/webpack.config.js",
}
执行 npm run dev 之后浏览器将会在本地开启服务