个人主页:爱吃炫迈
系列专栏:前端工程化
座右铭:道阻且长,行则将至
随着前端的快速发展,目前前端的开发已经变得越来越复杂了:
但是对于很多前端开发者来说,并不需要思考这些问题,日常的开发中根本就没有面临这些问题:
官方解释:webpack is a static module bundler for modern JavaScript applications.
解释:webpack是一个静态的模块化打包工具,为现代的JavaScript应用程序
两者关系:
- 执行webpack命令,会执行node_modules下的.bin目录下的webpack;
- webpack在执行时是依赖webpack-cli的,如果没有安装就会报错;
- 而webpack-cli中代码执行时,才是真正利用webpack进行编译和打包的过程;
- 所以在安装webpack时,我们需要同时安装webpack-cli(第三方的脚手架事实上是没有使用webpack-cli的,而是类似于自 己的vue-service-cli的东西)
// 全局安装
npm install webpack webpack-cli -g
// 局部安装
npm install webpack webpack-cli -D
- 创建package.json文件,用于管理项目的信息、库依赖等
npm init
- 安装局部的webpack
npm install webpack webpack-cli -D
- 使用局部的webpack
npx webpack
- 在package.json中创建scripts脚本,执行脚本打包即可
npm run build
- 可以通过webpack进行打包,之后运行打包之后的代码
- 在目录下直接执行webpack命令:
webpack
- 生成一个dist文件夹,里面存放一个main.js的文件,就是我们打包之后的文件:
- 这个文件中的代码被压缩和丑化了
- 另外我们发现代码中依然存在ES6的语法,比如箭头函数、const等,这是因为默认情况下webpack并不清楚我们打包后的文 件是否需要转成ES5之前的语法,后续我们需要通过babel来进行转换和设置
- 是可以正常进行打包的,但是有一个问题,webpack是如何确定我们的入口的呢?
- 事实上,当我们运行webpack时,webpack会查找当前目录下的
src/index.js
作为入口。所以,如果当前项目中没有存在src/index.js文件,那么会报错- 当然我们也可以通过配置来制定入口和出口
npx webpack --entry ./src/main.js --output-path ./build
入口起点(entry point) 指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
默认值是 ./src/index.js
,但你可以通过在 webpack configuration 中配置 entry
属性,来指定一个(或多个)不同的入口起点。例如:
webpack.config.js
module.exports = {
entry:'./src/main.js'
}
output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是 ./dist/main.js
,其他生成文件默认放置在 ./dist
文件夹中。
你可以通过在配置中指定一个 output
字段,来配置这些处理过程:
webpack.config.js
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',
},
};
在上面的示例中,我们通过 output.filename
和 output.path
属性,来告诉 webpack bundle 的名称,以及我们想要 bundle 生成(emit)到哪里。可能你想要了解在代码最上面导入的 path 模块是什么,它是一个 Node.js 核心模块,用于操作文件路径。
webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效模块,以供应用程序使用,以及被添加到依赖图中。
webpack的其中一个强大的特性就是能够通import导入任何类型的模块(例如.css文件),其他打包程序或任务执行器的可能并不支持。我们认为这种语言扩展是很有必要的,应为这可以是开发人员能够创建出更准确的依赖关系图
使用loader
import
语句中显示指定loader在引入的样式前加上使用的loader,并且使用!分割
import "css-loader!../css/style.css"
CLI方式(webpack5中不再使用)
配置方式:在webpack.config.js
文件中指定loader
loader 配置方式
配置方式的意思是我们的webpack.config.js文件中写明配置信息:
- module.rules中允许我们配置多个loader(因为我们也会继续使用其他loader,来完成其他文件的加载)
- 这种方式可以更好的表示loader的配置,也方便后期的维护,同时也让我们对各个loader有一全局的概览
module.rules的配置如下:
rules属性对应的值是一个数组:[Rule]
数组中存放的是一个个的Rule,Rule是一个对象,对象可以设置多个属性:
loader 从右到左(或从下到上)地取值(evaluate)/执行(execute)。在下面的示例中,从 css-loader 开始执行,以 style-loader 为结束。
webpack.config.js
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',
},
module: {
rules:[
{
test:/\.css$/,
use:[
{ loader: "style-loader"}
{ loader: "css-loader" }
]
// 写法2
//use:[ "style-loader", css-loader" ]
// 写法三
//loader: "style-loader", "css-loader"
}
]
}
};
以上配置中,对一个单独的 module 对象定义了 rules
属性,里面包含两个必须属性:test
和 use
。这告诉 webpack 编译器(compiler) 如下信息:
“嘿,webpack 编译器,当你碰到「在
require()
/import
语句中被解析为 ‘.css’ 的路径」时,在你对它打包之前,先 use(使用)css-loader
和style-loader
转换一下。”
加载css文件来说,我们需要一个可以读取css文件的loader,这个loader最常用的是css-loader。如果只是使用css-loader来加载css文件,我们会发现这个css在我们的代码中并没有生效(页面没有效果),这是因为css-loader只是负责将.css文件进行解析,并不会将解析之后的css插入到页面中,如果我们希望再完成插入style的操作,那么我们还需要另外一个loader,就是style-loader。
在我们的开发中,我们可能会使用less、sass、stylus的预处理器来编写css样式,效率会更高。那又该如何处理less文件呢?
首先,less、sass等编写的css需要通过工具转换成普通的css,然后再处理样式
module: {
rules:[
{
test:/\.less$/,
use:[
{ loader: "style-loader"}
{ loader: "css-loader" },
{ loader: "less-loader" }
]
}
]
}
loader特性
loader用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量
想要使用一个插件,你只需要 require()
它,然后把它添加到 plugins
数组中。
new
操作符来创建一个插件实例。webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin'); const webpack = require('webpack'); // 用于访问内置插件 module.exports = { module: { rules: [{ test: /\.txt$/, use: 'raw-loader' }], }, plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })], };
在上面的示例中,
html-webpack-plugin
为应用程序生成一个 HTML 文件,并自动将生成的所有 bundle 注入到此文件中。
举个栗子:使用postcss工具自动添加浏览器前缀
什么是postcss?
postcss是一个可以通过JavaScript来转换样式的工具,这个工具可以帮助我们进行一些css的转换和适配,比如自动添加浏览器前缀,css样式的重置,但是实现这些功能,我们需要借助于postcss对应的插件。
如何使用postcss?
- 查找postcss在构建工具中的扩展,比如webpack中的postcss-loader
- 选择可以添加你需要的postcss相关插件
webpack.config.js
module: {
rules:[
{
test:/\.css$/,
use:[ "style-loader", "css-loader", "postcss-loader" ]
}
]
}
因为postcss需要有对应的插件才会起效果,所以需要配置它的plugin:autoperfixer
module: {
rules:[
{
test:/\.css$/,
use:[ "style-loader", "css-loader",
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: [
"autoprefixer"
]
}
}
}
]
}
]
}
我们可以将这些配置信息放到一个单独的文件中进行管理:
在根目录下创建postcss.config.js
postcss.config.js
module.exports = {
plugins: [
require("autoprefixer")
]
}
webpack.config.js
module: {
rules:[
{
test:/\.css$/,
use:[ "style-loader", "css-loader", "postcss-loader" ]
}
]
}
Mode配置选项,可以告知webpack使用相应模式的内置优化:
选项 | 描述 |
---|---|
development | 会将DefinePlugin中的process.env.NODE_ENV的值设置为development,为模块和chunk启用有效的名 |
production | 会将DefinePlugin中的process.env.NODE_ENV的值设置为production,为模块和chunk启用确定性的混淆名称 |
none | 不使用任何默认优化选项 |