打包静态文件
Loader
前序问题:
webpack 是什么?
模块是什么
webpack 配置文件的作用是什么?
回答:1.webpack 是模块打包工具。
模块是项目中的 js 文件、css、或者是一张图片等。
配置文件是配置如何去打包模块
打包图片文件 webpack 可以打包 js 文件,但是非 js 文件需要手动在模块中定义如何打包。以 jpg 文件为例,看代码中如何配置.其他类型的文件同理,需要用对应的 loader 去配置
1 2 3 4 5 6 7 8 9 10 11 12 13 [webpack.config.js]; module .exports = { module : { rules: [ { test: /\.jpg$/ , use: { loader: "file-loader" , }, }, ], }, };
module 是个对象,包含的 rules 是数组,数组中定义了以 jpg 结尾的文件名(正则表达式),这样的文件用file-loader这个 loader 来打包。
当然,需要用 npm 安装这个 file-loader。
file-loader 做了什么?
它发现有.jpg 结尾的文件后,就把它打包移动到 output 目录(这里是 dist)并重命名(名字也可以在配置文件中自定义)。得到图片名称后,会把名字作为返回值,返回给引入模块的变量中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [index.js]; var Header = require ("./header.js" );var Sidebar = require ("./sidebar.js" );var Content = require ("./content.js" );var avatar = require ("./avatar.jpg" );console .log(avatar);new Header();new Sidebar();new Content();var img = new Image();img.src = avatar; var root = document .getElementById("root" );root.appendChild(img);
vue 文件同理要用 vue-loader
自定义静态文件打包后的名字/路径等信息 通过配置 loader 的 option 参数。
1 2 3 4 5 6 7 8 9 10 11 12 { test: /\.jpg$/ , use: { loader: "file-loader" , options: { name: "[name].[ext]" , outputPath: "images/" , }, }, },
name: "[name].[ext]"这种语法叫 placeholder 占位符。在官网可以查到各种占位符如[hash]等等。
url-loader 这个 loader 同样可以打包 jpg|png|gif 等图片文件,但不是把图片打包到 dist 文件夹的方式,而是把图片转换为 base64 编码,直接放入 bundle.js 文件中。节省一次 http 请求,但会浪费加载时间。
所以 url-loader 有一个配置 limit,如果图片大于 limit,就打包成图片文件,如果小于 limit,就打包到 bundle.js 中,配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 { test: /\.jpg$/ , use: { loader: "file-loader" , options: { name: "[name].[ext]" , outputPath: "images/" , limit : 10240 }, }, },
打包样式文件 需要用到 [“style-loader”, “css-loader”]
1 2 3 4 5 { test: /\.css$/ , use: ["style-loader" , "css-loader" ], },
css-loader:分析出几个 css 文件之间的关系,最终把这几个 css 文件合并成一段 css。
style-loader:把 css-loader 生成的 css 代码片段挂载到页面的 header 部分。
scss less stylus .scss 结尾的需要额外的 sass-loader 去把.scss 文件翻译成 css 文件
1 2 3 4 5 { test: /\.css$/ , use: ["style-loader" , "css-loader" , "sass-loader" ], },
loader 的执行是有顺序的, 顺序是从下到上,从右到左
自动添加厂商前缀 1 2 3 4 5 { test: /\.css$/ , use: ["style-loader" , "css-loader" , "sass-loader" , "postcss-loader" ], },
通过查看 webpack 官网的 loader,发现 postcss-loader 需要配置文件。
1 2 3 4 5 [postcss.config.js]; module .exports = { plugins: [require ("autoprefixer" )], };
并安装这个 autoprefixer 插件,就可以实现自动添加厂商前缀的效果了,可以在打包后的 html 文件用浏览器打开查看。
css-loader 中的 importLoaders
importLoaders查询参数 importLoaders,用于配置「css-loader 作用于 @import 的资源之前」有多少个 loader。
webpack.config.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 { test: /\.css$/ , use: [ 'style-loader' , { loader: 'css-loader' , options: { importLoaders: 2 modules : true } }, 'postcss-loader' , 'sass-loader' ] }
在模块系统(即 webpack)支持原始 loader 匹配后,此功能可能在将来会发生变化。
当一个 scss 文件中@import 了新的 scss 文件,此时对原文件的打包已经按顺序加载到了 css-loader 的功能,引入的 scss 文件用 css-loader 加载就会出错。这个importLoaders用来使引入的 scss 文件依然从 sass-loader 开始加载。
css 打包的模块化 在入口文件中引入的样式文件会作用在全局,可能会出现意外的样式覆盖问题,所以引入 css 模块化概念。
只需要加一句modules:true即可开启。
对应的,在入口文件中也需做修改,注意:如果依然按全局引入的话样式会不生效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 [index.js]入口文件 import avatar from "./avatar.jpg" ;import Avatar from "./avatar" ;import style from "./index.scss" ; Avatar(); var root = document .getElementById("root" );var img = new Image();img.classList.add(style.avatar); img.src = avatar; root.append(img); 打包后: <img class ="_17cnVz87yzSOO5TpFdnLsk" src="images/avatar.jpg" >
在其他 js 文件中使用同理。
打包字体文件 如 iconfont 的eot .ttf .svg .woff等,需要额外的 loader 去进行打包。这里使用的是 file-loader。配置与 url-loader 类似。
最后附上完整文件,github 地址
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 [webpack.config.js]; const path = require ("path" );module .exports = { mode: "development" , entry: { main : "./src/index.js" }, output: { filename: "bundle.js" , path: path.resolve(__dirname, "dist" ), }, module : { rules: [ { test: /\.(jpg|png|gif)$/ , use: { loader: "url-loader" , options: { name: "[name].[ext]" , outputPath: "images/" , limit: 10240 , }, }, }, { test: /\.(eot|ttf|svg|woff)$/ , use: { loader: "file-loader" , options: { name: "[name].[ext]" , outputPath: "font/" , }, }, }, { test: /\.scss$/ , use: [ "style-loader" , { loader: "css-loader" , options: { importLoaders: 2 , }, }, "postcss-loader" , "sass-loader" , ], }, ], }, };