什么是Webpack
Webpack 是一种用于构建 JavaScript 应用程序的静态模块打包器,它能够以一种相对一致且开放的处理方式,加载应用中的所有资源文件(图片、CSS、视频、字体文件等),并将其合并打包成浏览器兼容的 Web 资源文件。
Webpack可以忽略具体资源类型之间的差异,将所有代码/非代码文件都统一看作Module——模块对象,以相同的加载、解析、依赖管理、优化、合并流程实现打包,并借助Loader、Plugin两种开放接口将资源差异逻辑转交由社区实现,实现统一资源构建模型。借助 Loader,Webpack 几乎可以用任意方式处理任意类型的资源,例如可以用 Less、Stylus、Sass 等预编译 CSS 代码。
webpack基本使用
webpack的核心概念
Webpack 是一种 「配置」 驱动的构建工具,所以站在应用的角度,必须深入学习 Webpack 的各项配置规则,才能灵活应对各种构建需求。
Entry:入口,Webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。Module:模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。Loader:模块转换器,用于把模块原内容按照需求转换成新内容。Plugin:扩展插件,在 Webpack 构建流程中的特定时机会广播出对应的事件,插件可以监听这些事件的发生,在特定时机做对应的事情。
安装
npm install webpack webpack-cli -D
编辑配置文件
// webpack.config.js
const { resolve } = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: '[name].js',
path: resolve(__dirname, 'build')
},
mode: 'production'
};
// a.js
export const name = 'JavaScript';
export const age = "学习Webpack";
// b.js
import * as a from './a';
export { a };
// index.js
import * as b from './b';
console.log(b.a.name);
打包后生成代码
!function(e){var n={};function t(r){if(n[r])return n[r].exports;var o=n[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,t),o.l=!0,o.exports}t.m=e,t.c=n,t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{enumerable:!0,get:r})},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},t.t=function(e,n){if(1&n&&(e=t(e)),8&n)return e;if(4&n&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(t.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&n&&"string"!=typeof e)for(var o in e)t.d(r,o,function(n){return e[n]}.bind(null,o));return r},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=0)}([function(e,n,t){"use strict";t.r(n);var r={};t.r(r),t.d(r,"name",(function(){return o})),t.d(r,"age",(function(){return u}));const o="JavaScript",u="学习Webpack";console.log(r.name)}]);
借助预处理器、PostCss构建CSS工程环境
CSS 语言在过去若干年中一直在追求样式表现力方面的提升,工程化能力薄弱,例如缺乏成熟的模块化机制、依赖处理能力、逻辑判断能力等。为此,在开发现代大型 Web 应用时,通常会使用 Webpack 配合其它预处理器编写样式代码。我们如何使用CSS代码处理工具?使用css-loader、style-loader、mini-css-extract-plugin 处理原生 CSS 文件;如何使用 Less/Sass/Stylus 预处理器;如何使用 PostCSS?
-
css-loader:该 Loader 会将 CSS 等价翻译为形如module.exports = "${css}"的JavaScript 代码,使得 Webpack 能够如同处理 JS 代码一样解析 CSS 内容与资源依赖; -
style-loader:该 Loader 将在产物中注入一系列 runtime 代码,这些代码会将 CSS 内容注入到页面的<style>标签,使得样式生效; -
mini-css-extract-plugin:该插件会将 CSS 代码抽离到单独的.css文件,并将文件通过<link>标签方式插入到页面中。
css-loader使用
yarn add -D css-loader
修改webpack配置,定义规则
module.exports = {
module: {
rules: [
{ test: /\.css$/i,
use: ["css-loader"],
},
],
},
};
然后我们就可以执行npx webpack或其它构建命令即可,经过 css-loader 处理后还需要继续接入 style-loader 加载器。
style-loader并不会对代码内容做任何修改,而是简单注入一系列运行时代码,用于将css-loader转译出的 JS 字符串插入到页面的style标签。接入时同样需要安装依赖:
yarn add -D style-loader css-loader
之后修改 Webpack 配置,定义 .css 规则:
module.exports = {
module: {
rules: [
{
test: /.css$/i,
use: ["style-loader", "css-loader"],
},
],
},
};
注意保持 style-loader 在前,css-loader 在后。此时样式才真正开始生效。
使用预处理器
以Less为例,安装依赖
yarn add -D less less-loader
其次,修改 Webpack 配置,添加 .less 处理规则:
module.exports = {
module: {
rules: [{
test: /.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
]
}]
}
}
使用post-css
post-css实际上不是一个预处理器或后处理器,而是一个 CSS 处理工具的框架。如果你只需要编译 LESS 样式并在 Webpack 构建中使用,那么 less-loader 可能是一个不错的选择。如果你想要更广泛的 CSS 处理能力,例如自动添加浏览器前缀、优化和转换等,那么 PostCSS 是更适合的选择。当然,我们完全可以在同一个项目中同时使用两者。
PostCSS 的接入步骤也很简单,首先安装依赖:
yarn add -D postcss postcss-loader
之后添加 Webpack 配置:
module.exports = {
module: {
rules: [
{
test: /.css$/,
use: [
"style-loader",
"css-loader",
"postcss-loader"
],
},
],
}
};
不过,这个时候的 PostCSS 还只是个空壳,下一步还需要使用适当的 PostCSS 插件进行具体的功能处理,例如我们可以使用 autoprefixer 插件自动添加浏览器前缀,首先安装依赖:
yarn add -D autoprefixer
之后,修改 Webpack 配置:
module.exports = {
module: {
rules: [
{
test: /.css$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
importLoaders: 1
}
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
// 添加 autoprefixer 插件
plugins: [require("autoprefixer")],
},
},
}
],
},
],
}
};
之后,再次运行 Webpack 即可为 CSS 代码自动添加浏览器前缀。
总结
- Webpack 不能理解 CSS 代码,所以需要使用
css-loader、style-loader、mini-css-extract-plugin三种组件处理样式资源; - Less/Sass/Stylus/PostCSS 等工具可弥补原生 CSS 语言层面的诸多功能缺失,例如数值运算、嵌套、代码复用等。