写在头里,只是写给我自己的笔记,接受指正,不接受批评,内心太脆弱
首先,新建一个文件夹,当然文件夹的名称要是英文的,并进入当前文件夹。
初始化
npm init -y
安装webpack
npm install webpack webpack-cli --save-dev
webpack-cli 可以解析用户传入的参数(多是传入 mode),把解析好的参数传递给 webpack 进行打包,所以这俩模块都需要安装。
--save-dev 表示它是一个开发环境。
新建一个源码目录叫 src,在src目录下新建一个入口文件叫 index.js。
写法
webpack 默认支持模块的写法,也就是 commonJS规范,也就是 NODE 规范。
同样的也支持 es6 规范,也就是 esmodule。
比如,我在 src 目录下新建了一个 a-module.js 的文件,并在此文件中导出了一句话
module.exports = '我是谁,我在哪'
然后在 index.js 中去导入
let result = require('./a-module');
console.log(result);
就可以拿到 a-module.js 导出的结果
此处问题来了,我是要在浏览器中运行的,但浏览中是没有 require 和 module.exports的。
所以我需要把模块的结果进行打包,解析出浏览器可以识别的代码。
执行方式
npx webpack
npx 是 node 5.2 版本之后出来的,它的功能是可以帮我们执行 node_modules/.bin 文件夹下的某个文件,此处我们要执行的是 webpack
???? 我的npx 执行不成功
还可以把执行放到命令中
进入 package.json 中
"scripts": {
"build": "webpack --mode production"
},
运行
npm run build
npm run 的作用是把 node_modules/.bin 目录中放到全局上,那全局中就会有这些命令了,但它只是瞬间的,执行完后就被销毁了。
"scripts": {
"dev":"webpack --mode development",
"build": "webpack --mode production"
},
这样我们就可以通过命令来进行打包了
webapck 配置文件叫 webpack.config.js 或 webpack.file.js,我们多用的是 webpack.config.js。
上面这种说的是 webpack 0 配置打包,但这种方式比较傻,就是入口必须叫 index.js ,打包出来的也都是 dist/main.js ,不够灵活。
新建 webapck.config.js,接下来我们就来写 webpack 的配置文件了。 因为webpack是commonjs规范,所以默认需要导出一个配置对象
module.exports = {}
配置文件最少要有两项,一项是入口,一项是出口,先来说入口
module.exports = {
// 入口
entry:'./src/index.js'
}
入口的写法有两种,一种是这样的相对路径,但这会有一个问题,比如说我的入口移动目录了,那就找不到了,所以为了方便,我们写路径都采用绝对路径。
那怎么采用绝对路径的,都说了webpack是基于node规范的,那就可以使用node的一个模块叫 path , 先引入。
const path = require('path');
module.exports = {
// 入口
entry:path. (__dirname,'./src/index.js')
}
path 有个方法叫 resolve,它是用来解析绝对路径的,__dirname 是以当前根目录为基准,意思就是以当前文件夹为根目录,找到src下的index.js文件。 不信来看,运行的方法也是选中代码后右击,选择 run code(上面那张图上有)
const path = require('path');
module.exports = {
// 入口
entry:path.resolve(__dirname,'./src/index.js'),
// 出口
output:{
filename:'bundle.js', // 打包出来的文件名
path:path.resolve(__dirname,'dist') // 放到哪个文件夹下
}
}
运行试一下来
很好,成了,但我现在觉得在 scripts 中配置 mode 好麻烦,我想在配置文件中配,怎么配呢。
"scripts": {
"dev":"webpack",
"build": "webpack"
},
你看,我们把刚才配的 mode 给删了,相对应的在 webpack.config.js 中多加了一项。
const path = require('path');
module.exports = {
mode:'development', // 在此处传入 mode,表示当前是开发模式
// 入口
entry:path.resolve(__dirname,'./src/index.js'),
// 出口
output:{
filename:'bundle.js', // 打包出来的文件名
path:path.resolve(__dirname,'dist') // 放到哪个文件夹下
}
}
可以再运行一下试试,不报错就是对的,我就不贴图了,反正我的也没报错。 这么多配置项都写在一个文件中好乱啊,而且还有开发模式和生产模式不同的配置项怎么区分啊,我们来拆分一下吧。 我想在执行 npm run 时,通过传入不同的变量而去读不同的配置文件,我们来改造一下吧。
"scripts": {
"dev":"webpack --env.development",
"build": "webpack --env.production"
},
唉,有意思了,我这个传入的环境变量是哪儿来的呢?
是这样的,webpack.config.js 不光可以导出一个对象,它还可以导出一个函数
module.exports=(env)=>{
// env 就是环境变量,变量可以自挂属性
console.log(env);
// 函数要求返回配置文件,没返回会采用默认配置
}
再运行下看看来
新建个文件夹,叫 config ,专门用来放打包的配置,并在config文件夹中新建三个配置js,分别是 webpack.base.js 和 webpack.dev.js 和 webpack.prod.js
我们知道,它默认找的是 webpack.config.js ,那我咋才能让它根据我传的环境变量去找到相对应的文件呢?先来修改一下我们运行的命令
"scripts": {
"dev":"webpack --env.development --config ./config/webpack.base.js",
"build": "webpack --env.production --config ./config/webpack.base.js"
},
记得把刚才在 webpack.config.js 中导出的函数复制到 config/webpack.base.js 中去。
这里我用的是都去引 base ,在 base 中再去引对应环境的文件,记得要把 webpack.config.js 给删了,省得找错了,这样每次找的都是我们指定的 config/webapck.base.js 。
先在 base 中引入开发和生产的两个配置项,并进行配置合并。
const dev = require('./webpack.dev');
const prod = require('./webpack.prod');
const path = require('path');
const merge = require('webpack-merge');
module.exports=(env)=>{
// 定个变量,用来区别是不是 dev 模式
let isDev = env.development;
const base = {
entry:path.resolve(__dirname,'../src/index.js'),
output:{
filename:'bundle.js',
path:path.resolve(__dirname,'../dist')
}
}
// 将 env 的不同,将各自的配置和 base 的配置合并在一起,可以写个循环一项项合并
// 太麻烦了,此处借用 webpack-merge 模块来合并,它是主要用来合并配置文件的 npm install webpack-merge --save-dev
if(isDev){
// 如果是开发环境
// 自动合并两个配置,如果是有重复项,则会后面的覆盖前面的
return merge(base,dev);
}else{
// 否则是生产环境,当然如果环境多的话可以继续区分
return merge(base,prod);
}
}
好了,我们该让 webpack 帮我们起一个本地服务了,此处用到的是 webpack-dev-server,先安装一下 npm install webpack-dev-server --save-dev
它的用法很简单,只需要在运行时把 webpack 换成 webpack-dev-server 就行,webpack-dev-server只会在内存中打包,也就是说它不会形成实体文件。
"scripts": {
"dev": "webpack-dev-server --env.development --config ./config/webpack.base.js",
"build": "webpack --env.production --config ./config/webpack.base.js"
},
但这时,我想在开发时想看看打包出来的长啥样,咋办?再配置一个命令,在dev环境中的打包
"scripts": {
"dev:build": "webpack --env.development --config ./config/webpack.base.js",
"dev": "webpack-dev-server --env.development --config ./config/webpack.base.js",
"build": "webpack --env.production --config ./config/webpack.base.js"
},
我们先来看看 dev 有没有帮我起个服务
const path = require('path');
module.exports = {
mode:'development',
devServer:{
// 开发服务的配置
port:8888, // 端口号
compress:true,// gzip 可以提升返回页面的速度,它会减少代码的体积
contentBase:path.resolve(__dirname,'../dist') // webpack 启动目录在dist文件下
}
}
接下来我们来写个页面,自动生成一个打包后的页面并且让页面自动引入我们的JS。
(此处我删除了 dist 文件夹)
新建一个单独存放模板的目录,此处我们叫 public,并且在 public 下新建一个 index.html 页面。
npm install html-webpack-plugin --save-dev
插件永远不变的两步,一:引入,二:new
const dev = require('./webpack.dev');
const prod = require('./webpack.prod');
const path = require('path');
const merge = require('webpack-merge');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports=(env)=>{
// 定个变量,用来区别是不是 dev 模式
let isDev = env.development;
const base = {
entry:path.resolve(__dirname,'../src/index.js'),
output:{
filename:'bundle.js',
path:path.resolve(__dirname,'../dist')
},
plugins:[
new HtmlWebpackPlugin({
// 模板
template:path.resolve(__dirname,'../public/index.html'),
// 打包出来的文件名
filename:'index.html' ,
minify:!isDev && {
removeAttributeQuotes:true, // 把双引号去掉
collapseWhitespace:true, // 压缩成一行
} // 生产环境中的压缩 开发环境就不管了
})
]
}
// 将 env 的不同,将各自的配置和 base 的配置合并在一起,可以写个循环一项项合并
// 太麻烦了,此处借用 webpack-merge 模块来合并,它是主要用来合并配置文件的 npm install webpack-merge --save-dev
if(isDev){
// 如果是开发环境
// 自动合并两个配置,如果是有重复项,则会后面的覆盖前面的
return merge(base,dev);
}else{
// 否则是生产环境,当然如果环境多的话可以继续区分
return merge(base,prod);
}
}
npm install clean-webpack-plugin --save-dev
它可以默认帮我们清除输出的目录。
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
...
plugins:[
new CleanWebpackPlugin({
// 在打包之前清除,后面可以是正则,此处表示将我打包的目录下的所有文件清除
// 其实默认也是这样的,可以不写
cleanAfterEveryBuildPatterns:['**/*']
}),
...
]
...