教你从零开始写一个简单的webpack打包配置
这篇文章的全部代码已经上传到github。有需要的童鞋可以去看看。
github.com/Link-X/webp… 先简单看一下我们这个教程最终的文件结构
正文开始-------
千里之行始于足下。首先我们先新建一个文件夹,简单点就叫pack吧
打开这个文件夹,此时文件夹里什么都没有
第一步:需要一个 package.json的文件。
我们通过yarn init(npm init也行) 命令行初始化一个。
如果你没有按照yarn或者npm的话去先去安装一个。这里就不细说了,这里推荐yarn。
1、npm安装方式:直接下载一个node,它自带npm。。
2、yarn安装方式:yarn安装教程点这个教程很详细。
安装完后输入 yarn init 不出意料会出现这些东西,项目名称、版本、说明、协议、存储地址等等
一步步确认下来后,pack文件夹就会出现一个 package.json的文件 打开这个package.json 这里面就是我们刚刚输入的东西。这是一个配置文件,主要是配置我们项目需要的包的。是一个纯json我们先不管管它(^_^)
第二步:安装依赖,首先安装这两个 webpack、webpack-cli
yarn add webpack webpack-cli -D
或者
yarn add webpack -D
yarn add webpack-cli -D
这时有同学会问,这个 yarn add *** -D 是啥意思呀,后面那个-D又是什么鬼。好 我们简单解释一下这条命令,这条命令的意思就是把 webpack、webpack-cli 这两个第三方插件添加到开发时依赖。也就是说虽然我们安装了这两个包,但是我们只是希望在开发的时候使用它们,生产环境的代码可别有它们的身影。-D是--save-dev的简写, 意思安装的包到开发环境依赖。最终webpack 打包的时候会去读取 package.json。然后通过它会知道哪些是开发依赖,哪些是生产依赖。当然还有很多别的。这里只是简单介绍一下
打开 package.json,发现里面多了一个devDependencies, 刚刚我们add的哪两个开发依赖就在这里。 细心的同学可能已经发现,文件里还多了一个 node_modules的文件夹。打开一看,发现里面多了一大堆乱七八糟的东西。电脑配置不高的童靴光是把它删除就可能就要卡一两分钟,当然你千万别测试电脑性能删了它(ememem~~!)。为什么这个文件这么大腻,咱们只是安装了两个插件而已。这因为我们安装的这两个东西它也有他自己的依赖。它的依赖又可能依赖了别的依赖。如此循环~~ 啊哈哈。
这只是一个简单的解释。它里面还有一些特殊的文件夹。比如.bin 这是存放一些命令的文件。说到这个.bin 那么,童靴们接下来我们要搞一些事情。
首先在pack文件夹下,我们新建一个 src文件。在src文件下又新建一个 index.js,里面什么都不写
再打开刚刚生成的package.json。在里面新增一条数据。
"scripts": {
"build": "webpack --mode production"
}
复制代码
然后,在控制台执行 yarn build
卧槽什么情况。没错,是的此时以你已经精通webpack。变身 webpack 配置大失。
是不是很简单。啊哈哈哈~~~。就是这么简单!
嘿嘿,好啦,其实这只是一个开始,刚刚说到.bin文件夹,解释一下我们新增的再package.json 里的 scripts,里面的命令 就是在执行的时候自动新建一个 Shell,在这个 Shell 里面执行指定的脚本命令,比如 yarn build,会将当前目录的node_modules/.bin子目录加入PATH变量,执行结束后,再将PATH变量恢复原样。
第三步: 自定义配置webpack 配置
刚刚的操作并不能完成我们日常的需求,接下来我教大家如何,自定义配置webpack。首先我们新建一个 webpack.config.js 文件
当我们执行打包命令的时候,webpack会默认读取这个文件。获取用户自定义的配置。这个配置文件本质上是一个node的脚本,所以灵活性比较高
首先是入口(entry):入口是什么?webpack 的入口就是 从这个文件开始,以这里为起点开始依赖的所以东西全部打包。像一条线把你的代码连起来。
// module.exports 是node默认支持的CMD模块语法,我们这里的意思就是导出一个字面量对象,让webpack读取来当它的配置。详细可以自行搜索CMD模块
module.exports = {
// 这是单入口的配置写法
entry: './src/index.js'
}
module.exports = {
// 这是多入口的写法
entry: {
foo: './src/top.js',
bar: './src/bottom.js',
// ...
}
}
复制代码
然后出口(output):
啥是出口,顾名思义,就是指 webpack 最终构建出来的静态文件
// 有童鞋问着个path.resolve(__dirname, 'dist')是啥呀。
// path.resolve() 如果有参数 返回这个参数相对于当前的工作目录的绝对路径
// __dirname 这个也是node的一个api,意思是这个被执行的文件的绝对路径
// path.resolve(__dirname, 'dist')返回当前工作目录被执行文件(webpack.config.js)的绝对路径的下的dist。
// 总之咱么这就是返回 pack下dist 在你电脑的绝对路径
const path = require('path')
module.exports = {
...
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js'
}
}
复制代码
在然后是loader:
啥loader? 刚刚我们说了 webpack会从入口开始把你的代码连起来,连起来然后呢?烤了吃?^_^ 当然不是。webpack会通loader 把他们都转换了。转换它干啥?为啥要转换。我写的代码这么吊,还需要转换么...
开个玩笑,当然要转换。loader的目的就是转换你的代码,比如 我们知道css 有些属性还处于实验阶段,需要你加入一个前缀浏览器才回去识别他们,如 --ms-- --webkit-- 。
还有js 有些新api 特性等 浏览器厂商可能还没实现。咋办呢,咱么通过loader 转换一下就可以把我们自己写的新代码,让没有它可以在浏览器上执行。
还有less sass 等浏览器天生并不能能识别它们。需要一个转换。
module.exports = {
...
...
module: {
rules: [
{
test: /\.js$/, // 需要转换的文件,这里用正则匹配所以.js文件
loader: 'babel-loader', // 指定用到的那个loader去转换
include: [path.resolve(__dirname, 'src')] // 指定loader从哪里转换文件
}
]
},
}
复制代码
对了,这个 babel-loader 还需要一个单独的配置文件。别方,我们简单配置一下即可。 pack 目录下新建一个 .babelrc 文件
里面写{
"presets": ["es2015", "stage-2"],
"plugins": []
}
复制代码
babel-loader 是个第三方插件,我们需要安装一下,只需要在开发环境依赖即可
yarn add babel-loader babel-cli babel-preset-es2015 babel-preset-stage-2 -D
然后是plugins:
plugins 是啥?plugins 就是除了loader之外的所以事,都是plugins做,比如压缩代码什么的。
const UglifyPlugin = require('uglifyjs-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
...
...
...
plugins: [
new UglifyPlugin(), // 压缩文件
new HtmlWebpackPlugin({
filename: 'index.html', // 配置输出文件名和路径
minify: { // 压缩 HTML 的配置
minifyJS: true // 压缩 HTML 中出现的 JS 代码
}
})
]
}
复制代码
这里我们也需要安装一下uglifyjs-webpack-plugin 、 html-webpack-plugin ,两个分别是压缩文件的,和帮我们生成一个index.html的,两个都是开发依赖
yarn add uglifyjs-webpack-plugin -D
yarn add html-webpack-plugin -D
最后我们再说一个resolve 配置:
module.exports = {
...
...
...
...
resolve: {
extensions: [".wasm", ".mjs", ".js", ".json"], // 查找文件顺序
alias: {
"@": path.resolve(__dirname, 'src') // 路径别名,以后导入模块,前面加一个@就是当如src下的xxx
}
}
}
复制代码
引入的时候有时候我们会省略后缀,不如后面那个.js .html 这个 extensions 就是配置webpack 用那个后缀优先查找文件. alias 的意思就是配置一个路径别名,用过vue的人应该比较熟悉这个。 如
import test from '@/test/index.js'
复制代码
就是导入当前目录src下的test/index.js
在提一下通过es6或者cmd 模块引入一个模块,首先会去找是否当前目录,当前没目录没有会去找上级,最后到根目录,如果还是没有就会找node_module 。要是还是没找到就报错.
最后我们的完整配置就是
// webpack.config.js
const path = require('path')
const UglifyPlugin = require('uglifyjs-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js'
},
module: {
rules: [{
test: /\.js$/, // 用 babel-loader 解析js
loader: 'babel-loader',
include: [path.resolve(__dirname, 'dist')]
}]
},
plugins: [
new UglifyPlugin(), // 压缩文件
new HtmlWebpackPlugin({
filename: 'index.html', // 配置输出文件名和路径
minify: { // 压缩 HTML 的配置
minifyJS: true // 压缩 HTML 中出现的 JS 代码
}
})
],
resolve: {
extensions: [".wasm", ".mjs", ".js", ".json"], // 查找文件顺序
alias: {
"@": path.resolve(__dirname, 'src') // 路径别名,以后导入模块,前面加一个@就是当如src下的xxx
}
}
}
复制代码
我们在src/index.js下写一行 console.log(1) 然后执行一下 yarn build
打包成功. 打开dist/index.html 没错熟悉的味道.然后是热更新,这块我也不是很熟悉。简单贴一下配置吧,
pack下新建一个config文件夹,然后新建一个server.js
里面写
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const webpackHotMiddleware = require("webpack-hot-middleware")
const webpackOptions = require('../webpack.config.js')
const path = require('path')
webpackOptions.mode = 'development'
const compiler = webpack(webpackOptions),
express = require('express'),
app = express(),
DIST_DIR = path.join(__dirname, '..', 'dist')
const devMiddleware = webpackDevMiddleware(compiler, {
publicPath: webpackOptions.output.publicPath,
quiet: true
})
const hotMiddleware = webpackHotMiddleware(compiler, {
log: false,
heartbeat: 2000
})
app.use(devMiddleware)
app.use(hotMiddleware)
app.listen(3000, () => console.log('http://localhost:3000'))
复制代码
然后需要安装一下三个需要用的的热更新的插件
yarn add webpack-dev-middleware webpack-hot-middleware express -D
在webpack.config.js 改三个小小的地方.
// 1、新增导入 webpack
const webpack = require('webpack')
// 2、入口改成这样
entry: {
main: ['webpack-hot-middleware/client.js?reload=true', './src/index.js']
}
// 3、plugins 改成这样
plugins: [
new UglifyPlugin(), // 压缩文件
new HtmlWebpackPlugin({
filename: 'index.html', // 配置输出文件名和路径
minify: { // 压缩 HTML 的配置
minifyJS: true // 压缩 HTML 中出现的 JS 代码
}
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin()
]
//
复制代码
最后在 package.json 的scripts 加入"start": "node config/server.js"
// 如下
{
"name": "packTest",
"version": "0.01",
"description": "webpack初体验",
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "node config/server.js",
"build": "webpack --mode production"
},
"devDependencies": {
"babel-loader": "^8.0.4",
"express": "^4.16.4",
"html-webpack-plugin": "^3.2.0",
"uglifyjs-webpack-plugin": "^2.0.1",
"webpack": "^4.25.1",
"webpack-cli": "^3.1.2",
"webpack-dev-middleware": "^3.4.0",
"webpack-hot-middleware": "^2.24.3"
}
}
复制代码
yarn start .启动啦 访问 http://localhost:3000/
成功,随便修改src/index.js 下任意代码就可以看到也没自动刷新了