对于打包工具来讲,最简单也是最复杂的操做莫过于路径的安排了,本来都在src
下的资源,想要打包到dist
目录下,可是打包出来的文件路径甚不如人意。明明想要分门别类地放置文件文件,而后却像大杂烩同样js
,html
,css
甚至图片都混在了一块儿。虽然打包以后运行没什么问题,可是这是要逼死强迫症患者啊。css
因此这篇文章就是讲解如何明明白白安排各资源的路径,无关webpack性能,无关各种骚操做,只是基础的路径操做。html
传统的网站通常会将文件夹分为三类,styles
,scripts
,images
,看到这个三个文件夹就会倍感亲切,有种老朋友的感受。若是这个时候css文件出如今了scripts中,或者更images文件夹出如今scripts中,估计写这个网站的前端会被你们吐槽了。可是若是是webpack打包以后发生这种事,绝不惊奇,习觉得常,佛系打包。每次打包都是一个惊喜,若是配置不对,打包出来的文件可能会和你玩捉迷藏。为此我整理了下webpack打包中可能会出现的路径问题,以下方大纲所示,若是有伙伴们遇到过此类问题能够按需查询。前端
大纲:webpack
webpack打包流程简单来讲就是把全部的资源都变成js的chunk模块,而后再对chunk们进行操做,最后再根据配置分门别类输出。git
为了可以深刻了解咱们的文件打包去哪儿了,我建了一个比较变态的文件目录。github
JS在这个过程当中是最好控制的,根据配置的entry和output既能够轻松控制前因后果。而这两个配置在官方文档中也解释地至关详细。web
像下方这样的配置,应该比较经常使用,就是一个html,一个场景一个entry,而后output的时候按照entry名字生成相对应的文件。工具
entry:{ "index":path.resolve(__dirname,"src/scripts/index/index.js"), "list":path.resolve(__dirname,"src/scripts/list/list.js"), }, output:{ path:path.resolve(__dirname,"dist"), filename:"[name].js" },
这里须要注意:性能
filename:"scripts/[name].js"
,这样就会在dist目录下生成一个scripts的目录,JS打包以后都会生成在这个文件夹之中。CSS的引用,就比CSS复杂一些,不是直接HTML引用,而是import "../../styles/index/index.css"
像这样导入,或者require
到JS之中,这样webpack才会去打包CSS到新目录下。不过呢原生的CSS,JS是不认识的,因此这个时候须要loader帮咱们编译CSS才能导入JS之中。优化
css-loader很显然就是将CSS编译成JS认识的语法。
style-loader最主要干的事情就是将JS中编译的CSS代码插入DOM之中,使之生效。
mini-css-extract-plugin,这个插件最主要的目的就是将每一个JS(chunk)中的CSS代码剥离出来,分别打包到各自命名的CSS文件之中。(注:ExtractTextPlugin只适用于webpack3及如下。),有关CSS文件生成路径的问题,咱们主要就是用这个插件来实现,而这个插件不只要在loader的时候参与编译CSS,还须要在打包的时候发挥做用,将CSS打包到相应的文件夹之中。
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports={ ... //loader module: { rules: [ { test: /\.css$/, use: [ { loader: MiniCssExtractPlugin.loader, options: { publicPath: '../' } }, "css-loader" ] } ] , }, plugins: [ //css打包 new MiniCssExtractPlugin({ filename: "styles/[name].css" }) ] }
上述代码给出了MiniCssExtractPlugin这个插件的用法。它主要的生成配置是在filename:"styles/[name].css"
,这否以为似成相识,和webpack的output.filename的配置同样,能够将css打包至styles文件夹之下。
HTML的打包编译就比较特殊,通常使用html-webpack-plugin
插件,经过编写模版来配置生成html文件。这个插件的功能很强大,不过这里只说起生成路径的配置。
const HtmlWebpackPlugin = require('html-webpack-plugin');
我是这样配置html,导入模版,而后生成文件,我给filename一个绝对路径,这样就不用担忧文件会生成到什么奇怪的地方了。固然直接filename: 'index.html'
给一个文件名也是能够的,这样就会按照webpack中output配置的path,即项目目录为对象的相对路径。这里的chunks: ["index"]
使之html中包含的独立,不然会将全部的资源所有潜入当前的html中。
new HtmlWebpackPlugin({ filename: path.join(__dirname,'/dist/index.html'), template: path.join(__dirname,'/src/templates/index.html'), chunks: ["index"] })
这一块应该是最相对最复杂的一块了,不过度别分析以后也不会太负责。
这一部分是最简单的了,由于从JS中获取资源最直接,不用编译多道工序。
说到导入文件的地址,咱们最经常使用的是file-loader
这个loader。在outputPath
之中配置文件的生成地址。这里咱们配置了images/
,也就是dist/images
之下。useRelativePath
这个选项看似人畜无害,可是配置的时候需谨慎否则屡次调用这个loader的话,就会发生dist/images/images
的状况。
{ test: /\.(png|jpg|gif)$/, use: [ { loader: 'file-loader', options: { useRelativePath:false, outputPath: 'images/', name: '[name].[ext]' } } ] },
JS想要导入图片,也很简单直接import或者require+图片地址,便可,与CSS的调用一致。
在CSS中咱们常常会用到图片,好比background这个属性,那么在CSS中咱们怎么打包图片,而且改变CSS中图片的地址呢?由于咱们CSS是被import到JS之中的,因此和JS同样的处理方式,file-loader会帮助咱们处理好图片的问题的。不过CSS中图片的引用地址是个问题啊。
{ loader: MiniCssExtractPlugin.loader, options: { publicPath: '../' } }
这个时候就能够利用loader中publicPath这个属性,这个属性不参与编译,只在最后打包的时候替换路径。这里CSS中图片的路径是image/xxx.jpg
,若是咱们加上这个../
,那么就变成../image/xxx.jpg
。经过这样来控制CSS中图片的问题,若是想改为CDN地址也是能够。
这一部分是最使人头疼的file-loader
不处理html中的img标签,这里咱们会利用html-loader
来处理图片的问题,以下方配置:
{ test: /\.html$/, use: [ { loader: 'html-loader', options: { publicPath:"./", attrs: ['img:src'] } }], }
这样咱们就会将html中的图片文件完美的打包出来啦。不过这个插件没有publicPath的配置,这里的地址须要依靠output.publicPath。若是output.publicPath为空,那么打包出来的文件地址就是images/xxx.jpg
。若是配置了output.publicPath="./"
,那么打包出来的就是./images/xxx.jpg
。
打包路径说复杂各类相对路径确实容易搞晕,因此这个时候须要保持清醒的头脑。该用相对路径的用相对。不须要的就用绝对路径。有些插件仍是很人性化地有publicPath
这个选项,还能够手动控制下。
本文所用到的loader,plugin一览
plugin/loader | usage |
---|---|
file-loader | 用于管理JS中导入的资源或者CSS中引用的资源路径。 |
html-loader | 用于管理HTML,提取管理引用资源,如img中的src,还能够对html进行优化,如去除全部的注释压缩等。 |
mini-css-extract-plugin | 用于提取CSS,并进行分别打包,虽然有mini,可是意思不是压缩CSS,如需压缩还须要其余的插件配置。 |
html-webpack-plugin | 一个强大的html管理插件,能够用于生成html,能够配置模板,灵活的配置chunk。 |