9.路径相关

原来我们打包的东西都存放到了dist目录下,并没有进行分类存储,乱成一团,这一节我们就要处理一下打包的路径,让打包后的目录看起来更加优雅

9.1.代码准备

我们先建立起这样一个目录结构

.
├── node_modules
├── src
| ├── assets
| └── css
| └── index.css
| └── img
| └── noding.jpg
| └── js
| └── index.js
| └── index.html
├── .babelrc
├── package-lock.json
├── package.json
├── webpack.config.js
└── dist

  

你只需要把前面我们写的代码copy一份,然后删除掉dist里面的东西并且在src下新建assets文件夹来装css和img就可以了

我们在src/index.html中输入一段代码

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="box"></div>
<i class="fa fa-bath" aria-hidden="true"></i>
<i class="fa fa-envelope-open" aria-hidden="true"></i>
<i class="fa fa-microchip" aria-hidden="true"></i>
<i class="fa fa-user-circle-o" aria-hidden="true"></i>
</body>
</html>

  

接下来在assets/js/index.js中输入下面代码

// 引入icon图标字体
import "font-awesome/css/font-awesome.css" // 引入图片 import imgSrc from '../img/nodeing.jpg' // 把图片插入到html网页中 document.getElementById("box").innerHTML = '<img src="'+imgSrc+'" />'

  

然后去webpack.config.js中去修改一下入口文件位置

接下来,我们去测试一下打包效果

npm run dev

  

所有文件都打包到dist目录下,到此,我们这小节准备工作已经完成,接下来,我们需要去优化webpack配置,让打包出来的文件不那么混乱

9.2.webpack配置

9.2.1.把js文件分类

我们希望打包出来的文件也像src目录一样能够分门别类的存放,首先,我们把js单独放进assets/js文件夹下,这时我们需要修改webpack配置文件,把输出目录改掉

output: {
path: path.resolve(__dirname, 'dist/assets'),
filename: 'js/app.js'
},

  

运行npm run dev 查看效果,发现dist目录下多出了一个assets文件,并且已经建立好了js文件夹,app.js也被放进来了,但是,原来打包出来的那些文件还在,这时候,dist目录就更乱了,我们希望每次打包生成的文件都是最新的,得手动去删除上次打包出来的文件,像这种手动删除dist目录的操作,我们可以交给webpack相关插件来完成,这个插件叫clean-webpack-plugin

安装clean-webpack-plugin插件

npm install clean-webpack-plugin --save

  

修改webpack配置文件,引入clean-webpack-plugin插件

const path = require("path")

const HtmlWebpackPlugin = require("html-webpack-plugin")
// 引入clean-webpack-plugin插件
const CleanWebpackPlugin = require("clean-webpack-plugin") module.exports = {
entry: "./src/assets/js/index.js",
output: {
path: path.resolve(__dirname, 'dist/assets'),
filename: 'js/app.js'
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html'
}),
// 使用插件,设置需要清除的目录
new CleanWebpackPlugin(['dist'])
],
devServer: {
open: true
},
module: {
rules: [
{
test: /\.js$/,
use:['babel-loader'],
exclude: path.resolve(__dirname, 'node_modules')
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
// 处理文字
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: 'file-loader'
},
{
test: /\.(jpg|png|gif|webp|bmp)$/,
use: [{
loader: 'url-loader',
options: {
limit: 10240
}
}]
}
]
} }

  

这个时候你会发现,每次运行npm run dev,这个插件就会先把上次的dist目录删除,然后再新建一个dist目录,把新打包的文件放里面

以上步骤,我们把js文件放到了assets/js目录下,但随之而来的就是,所有的文件都被打包到assets这个目录下了,我们不希望index.html这个文件也被打包进assets目录下,而是像在src目录下一样,它们应该是同级的,所以我们需要修改一下 index.html被输出的路径

 plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
// 这里表示往外回退一层
filename: '../index.html'
}),
new CleanWebpackPlugin(['dist'])
],

  

9.2.2.把字体文件分类

修改webpack配置文件,给字体文件增加输出规则

 // 处理文字
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: [{
loader: "file-loader",
options: {
name: 'fonts/[name]_[hash:4].[ext]'
}
}]
},

  

其中,[name]、[hash]、[ext]都是可变的,name表示原来的文件名字,hash表示生成的hash值,hash:4表示可以限定hash字符串的位数,ext表示原来文件的扩展名(文件后缀)

9.2.3.把图片文件分类

修改webpack配置文件,给图片文件增加输出规则

 {
test: /\.(jpg|png|gif|webp|bmp)$/,
use: [{
loader: 'url-loader',
options: {
limit: 10240,
name: 'img/[name]_[hash:4].[ext]'
}
}]
}

  

因为,ulr-loader是对file-loader的封装,其中的[name]、[hash]、[ext]表示的意思和file-loader中表示的意思是一样的

9.2.4.把css文件分类

css文件是打包进js文件的,如果需要单独打包出来,需要安装另一个插件,extract-text-webpack-plugin

npm install extract-text-webpack-plugin --save-dev

  

这个插件的使用规则和其他plugin差不多,首先需要引入插件

const ExtractTextWebpackPlugin = require("extract-text-webpack-plugin")

  

其次,是需要实例化对象,并且传入配置项,然后将实例化出来的这个对象加入到plugins选项中

const extractcss = new ExtractTextWebpackPlugin({
//打包输出的路径
filename: 'assets/css/index.css'
})
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: './index.html'
}),
new CleanWebpackPlugin(['dist']),
// 这里是前面实例化得到的对象
extractcss
],

  

最后,需要修改css输出规则

{
test: /\.css$/,
use: extractcss.extract({
fallback:'style-loader',
use:['css-loader']
})
},

  

9.2.5.修正url地址

当我们把各种类型的文件分类好以后,运行打包出来的index.html,发现图片、字体、css等的路径是不正确的,没办法正常工作,这个时候,我们需要用output配置项下的 publicPath来修正一下

output: {
path: path.resolve(__dirname, 'dist/assets'),
filename: 'js/app.js',
publicPath: 'assets/'
},

  

其中,publicPath设置的是所有静态资源的基础目录,要快速理解它,可以记住下面的公式

静态资源最终访问路径 = output.publicPath + 资源loader或插件等配置路径

  

举例说明,我们在各种loader中设置的路径如下:

// css输出路径
name: 'css/[name]_[hash:4].[ext]'
// 图片输出路径
name: 'img/[name]_[hash:4].[ext]'
// 字体文件输出路径
name: 'fonts/[name]_[hash:4].[ext]'
// js文件输出路径
filename: 'js/app.js'

  

设置的publicPath为 "assets/", 那么最终的访问路径就是 publicPath/loader设置的路径,例如图片路径就会是 assets/img/[name]_[hash:4].[ext]

总结来说就是最终的url访问路径是拿publicPath+loader路径相拼接的

接下来,我们npm start启动我们的项目,发现最终访问的是项目的根目录,而并没有去访问打包出来的那个index.html文件,在找出没有访问到index.html文件的原因之前,我们先来讲清楚webpack中几个非常容易混淆的路径问题

1.output.path

2.output.publicPath

3.devServer.publicPath

4.devServer.contentBase

  

output.path 是静态资源的输出目录,打包后的资源都放到这里

output.publicPath是静态资源的基础目录,设置这个目录后,最终的静态资源访问路径前面都会拼接上这个选项设置的值,这也方便我们单独设置静态资源服务器地址,例如:静态资源服务器地址是http://static.nodeing.com, 设置了这个值,最终访问图片的地址就会是 http://static.nodeing.com/assets/img/nodeing.com 这种形式,因此,这也是output.publicPath这个选项和后面devServer.publicPath比较大的区别,前者是可以设置http网址的

devServer.publicPath这个选项是webpack-dev-server服务器的访问路径,我们知道当webpack-dev-server启动后,会把资源打包到内存,你不需要关注它在内存中的什么地方,你可以理解为打包后的资源也被输出了,只是输出到内存中,你无法在硬盘上看见而已,但是它提供了一个地址来供我们访问,devServer.publicPath就是用来设置访问内存中被打包出来的资源地址的,举例说明:

output: {
path: path.resolve(__dirname, 'dist/assets'),
filename: 'js/app.js',
},
devServer: {
open: true,
publicPath: '/aa'
},
其他配置省略...

  

像上面这种配置,当服务器启动的时候,如果想访问到内存中的app.js,那么需要通过http://localhost:8080/aa/js/app.js

回到开始的问题,npm start启动服务器后,无法访问到打包出来的index.html? 我们来找找具体的原因,说明一下几种路径的问题

当前的完整的webpack配置是这样的:

const path = require("path")

const HtmlWebpackPlugin = require("html-webpack-plugin")

const CleanWebpackPlugin = require("clean-webpack-plugin")

module.exports = {
entry: "./src/assets/js/index.js",
output: {
path: path.resolve(__dirname, 'dist/assets'),
filename: 'js/app.js',
publicPath: 'assets/'
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: '../index.html'
}),
new CleanWebpackPlugin(['dist'])
],
devServer: {
open: true,
containtBase: 'src/'
publicPath: '/aa'
},
module: {
rules: [
{
test: /\.js$/,
use:['babel-loader'],
exclude: path.resolve(__dirname, 'node_modules')
},
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
name: 'css/[name]_[hash:4].[ext]'
}
}
]
},
// 处理文字
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: [{
loader: "file-loader",
options: {
name: 'fonts/[name]_[hash:4].[ext]'
}
}]
},
{
test: /\.(jpg|png|gif|webp|bmp)$/,
use: [{
loader: 'url-loader',
options: {
limit: 10240,
name: 'img/[name].[ext]'
}
}]
}
]
} }

  

我们来解读几条关键的配置:

1.path: path.resolve(__dirname, 'dist/assets'), 这条配置是打包后资源输出的目录,同样的当webpack-dev-server启动后,资源会打包到内存,用不太严谨但通俗的话来说你可以认为所有文件被打包到这个目录,只是这个目录放在内存而不是输出到硬盘,你访问这个目录里面的文件的时候,路径和打包到硬盘是看到的路径一样,例如:在硬盘上 dist/assets/js/app.js, 在内存中也通过这种目录结构访问就是了

2.publicPath: 'assets/',这个配置,前面我们也讲到了,是静态资源的基础路径,可以返回去再阅读一下

3.publicPath: '/aa', 这个配置是服务器访问内存的虚拟路径, http://localhost:8080/aa 这个地址,你可以认为是映射到了output.path设置的目录,不太严谨但通俗的说,你可以认为http://localhost:8080/aa 这个地址指向了这个目录(dist/assets/),那么你在http://localhost:8080/aa后面加 /js/app.js 就相当于访问 dist/assets/js/app.js,所以启动以后通过http://localhost:8080/aa/js/app.js是可以访问到这个js文件的

4.filename: '../index.html',这个在HtmlWepackPlugin中的配置,设置了被打包出来的html位置,../表示往上一层返回,那就意味着,最终打包出来的结构是这样的:

├── dist
| ├── assets
| ├── css
| ├── img
| ├── js
| ├── index.html
|

  

我们通过http://localhost:8080/aa 能访问到dist/assets目录,也可以访问该目录下层级更深的文件,只需要在http://localhost:8080/aa 后面加文件路径就可以了,但是却永远无法返回到上层目录去访问到 index.html

当访问不到内存中的index.html文件,webpack-dev-server就会去访问本地的路径,这个本地的路径就是containtBase: 'src/'这个选项设置的,所以npm start的时候,直接打开的是项目下的src目录

好了,问题原因已经找出来了,接下来我们需要修改以下webpack配置,具体的思路就是

1. 输出目录往上挪动一层    output.path 设置成 path.resolve(__dirname, 'dist'),
2. 在每个loader上加深一层 js加深一层是这样的 assets/js/app.js 图片加深一层是这样的 assets/img/...,其他,同理
3. ../index.html 改为当前目录 ./index.html
4. output.publicPath的值设置来和devServer.publickPath的值一样,不然静态资源的访问地址会出错,返回404

这样做,原来打包输出的目录变成了dist目录,而不是原来的dist/assets目录, 那么http://localhost:8080/aa 这个地址指向的内存虚拟目录就是 dist目录,那么通过http://localhost:8080/aa/index.html 就可以访问到内容了

具体完整配置如下:

const path = require("path")

const HtmlWebpackPlugin = require("html-webpack-plugin")

const CleanWebpackPlugin = require("clean-webpack-plugin")

module.exports = {
entry: "./src/assets/js/index.js",
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'assets/js/app.js',
publicPath: '/aa/'
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: './index.html'
}),
new CleanWebpackPlugin(['dist'])
],
devServer: {
open: true,
publicPath: '/aa'
},
module: {
rules: [
{
test: /\.js$/,
use:['babel-loader'],
exclude: path.resolve(__dirname, 'node_modules')
},
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
name: 'assets/css/[name]_[hash:4].[ext]'
}
}
]
},
// 处理文字
{
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: [{
loader: "file-loader",
options: {
name: 'assets/fonts/[name]_[hash:4].[ext]'
}
}]
},
{
test: /\.(jpg|png|gif|webp|bmp)$/,
use: [{
loader: 'url-loader',
options: {
limit: 10240,
name: 'assets/img/[name].[ext]'
}
}]
}
]
} }

  

通常output.publicPath和devServer.publicPath设置成 "/",这样我们就可以通过 http://localhost:8080/ 来访问打包出来的index文件了,自己动手改改,试试效果吧!!

webpack最佳入门实践系列(5)的更多相关文章

  1. webpack最佳入门实践系列(6)

    10.css模块化 10.1.什么是css模块? CSS模块就是所有的类名都只有局部作用域的CSS文件,当你在一个JavaScript模块中导入一个CSS文件时,CSS模块将会定义一个对象,将文件中类 ...

  2. webpack最佳入门实践系列(4)

    7.使用字体 7.1.安装字体库-font-awesome 我们通过npm来安装字体 npm install font-awesome --save 这个时候,我们的package.json配置文件变 ...

  3. webpack最佳入门实践系列(3)

    6.使用图片 6.1.尝试在css中引入图片 在src目录下新建css文件夹,并且在css文件夹下创建app.css文件,在src目录下新建images文件夹,放入一张图片,在app.css中引入这张 ...

  4. webpack最佳入门实践系列(2)

    3.插件 在前端迅速发展的今天,许多没有太多技术含量并且感觉是在浪费时间的事情,就可以交给构建工具来做,例如:我们去手动创建index.html,手动引入打包好的js文件等操作,都可以叫个webpac ...

  5. webpack最佳入门实践系列(1)

    1.webpack简介 webpack 是一个现代 JavaScript 应用程序的模块打包器(module bundler).它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源 1 ...

  6. webpack的入门实践,看这篇就够了

    webpack的入门实践 我会将所有的读者概括为初学者,即使你可能有基础,学习本节之前我希望你具有一定的JavaScript和node基础 文中的 ... ...代表省略掉部分代码,和上面的代码相同 ...

  7. 【Vuejs】301- Vue 3.0前的 TypeScript 最佳入门实践

    前言 我个人对更严格类型限制没有积极的看法,毕竟各类转类型的骚写法写习惯了. 然鹅最近的一个项目中,是 TypeScript+ Vue,毛计喇,学之...-真香! 1. 使用官方脚手架构建 npm i ...

  8. python 最佳入门实践

    勿在浮沙筑高台,无论什么技术,掌握核心精神和api,是很重要的. 但是入门过程也可能不是一帆风顺的,这里有八个入门任务,看看你完成了没有: http://code.tutsplus.com/artic ...

  9. es6+最佳入门实践(13)

    13.模块化 13.1.什么是模块化 模块化是一种处理复杂系统分解为更好的可管理模块的方式.通俗的讲就是把一个复杂的功能拆分成多个小功能,并且以一种良好的机制管理起来,这样就可以认为是模块化.就像作家 ...

随机推荐

  1. python__基础 : 异常处理与自定义异常

    异常处理方法一般为: try: ------code----- except Exception as e: # 抛出异常之后将会执行 print(e) else: # 没有异常将会执行 print( ...

  2. HTML基本教程,及一些基本常用标签。

    HTML基本结构,及常用标签 <DOCTYPE html> <html> <head> <meta charset="UTF-8" /&g ...

  3. 学习python第十六天,正则表达式

    正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配.采取动态模糊的匹配,最大的应用是爬虫. re 模块使 Python 语言拥有全部的正则表达式功能. compile 函 ...

  4. 解决cmd 运行python socket怎么终止运行

    在cmd里启动python写了一个socket服务端的程序,但是启动之后由于监听连接的是一个死循环 这时想终止运行,发现按ctrl+c,ctrl+z,ctrl+d都不能终止 用ctrl+break解决

  5. [回文树][BZOJ2160][国家集训队]拉拉队排练

    题面 Description 艾利斯顿商学院篮球队要参加一年一度的市篮球比赛了.拉拉队是篮球比赛的一个看点,好的拉拉队往往能帮助球队增加士气,赢得最终的比赛.所以作为拉拉队队长的楚雨荨同学知道,帮助篮 ...

  6. spark练习--mysql的读取

    前面我们一直操作的是,通过一个文件来读取数据,这个里面不涉及数据相关的只是,今天我们来介绍一下spark操作中存放与读取 1.首先我们先介绍的是把数据存放进入mysql中,今天介绍的这个例子是我们前两 ...

  7. Java线程和多线程(七)——ThreadLocal

    Java中的ThreadLocal是用来创建线程本地变量用的.我们都知道,访问某个对象的所有线程都是能够共享对象的状态的,所以这个对象状态就不是线程安全的.开发者可以通过使用同步来保证线程安全,但是如 ...

  8. Altium Designer多原理图、PCB更新处理

    问题扫述: 一般一个同程有多个原理图.PCB.但是AD默认从原理图更新到PCB会把全部原理图都更新过去.因此需要稍加设置. 一.

  9. Eclipse 创建 Java 包---Eclipse教程第09课

    打开新建 Java 包向导 你可以使用新建 Java 包向导来创建 Java 包.Java 包向导打开方式有: 通过点击 "File" 菜单并选择 New > Package ...

  10. 《Cracking the Coding Interview》——第5章:位操作——题目4

    2014-03-19 06:15 题目:解释(n & (n - 1)) == 0是什么意思? 解法:n&n-1是去掉最低位‘1’的方法.根据运算符优先级,貌似用不着加那个括号,但位运算 ...