Vue提高18 更换打包文件路径

已同步到个人博客,欢迎访问。

一个由更改Vue打包后路径引发的一系列问题。

引入字体文件

在Vue中,想要引入字体文件,需要,使用@font-face来引入本地的字体



h1 {
  background: url('./assets/images/logo.png');
}

然后再App.vue中引入并使用


这样就可以使用引入的字体了。

也可以单独建立一个CSS文件来统一管理引入的字体,然后通过import引入


url-loader

Webpack中的loader的目的是用来处理各种非JS之外的文件,可以使你在import或"加载"模块时预处理文件。

执行的顺序是从右至左,在Vue-cli2中,在webpack.base.conf.js中定义了一些基本的loader:

module: {
  rules: [
    {
      test: /\.vue$/,
      loader: 'vue-loader',
      options: vueLoaderConfig
    },
    {
      test: /\.js$/,
      loader: 'babel-loader',
      include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
    },
    {
      test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
      loader: 'url-loader',
      options: {
        limit: 10000,
        name: utils.assetsPath('img/[name].[hash:7].[ext]')
      }
    },
    {
      test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
      loader: 'url-loader',
      options: {
        limit: 10000,
        name: utils.assetsPath('media/[name].[hash:7].[ext]')
      }
    },
    {
      test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
      loader: 'url-loader',
      options: {
        limit: 10000,
        name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
      }
    },
	{
	  test: /\.pug$/,
	  loader: 'pug',
	},
    {
      test: /\.less$/,
      loader: "style-loader!css-loader!less-loader",
    },
  ]
},

比较重要的是url-loader这个插件。我们在处理引入的各种资源文件时,Webpack最终会将各个模块打包成一个文件,因此我们样式中的URL路径是相对入口HTML页面的,而不是相对于原始CSS文件所在的路径的。这就会导致图片引入失败。这个问题可以使用file-loader解决。

url-loader中封装了file-loader,它不依赖于file-loader,它除了可以完成file-loader的作用,还可以将符合要求的图片进行编码生成DataURL,减少HTTP请求数目。url-loader选项中提供了limit参数,小于这个参数的文件才会转换为DataURL

路径

明确一下关于路径的表示,

./        表示当前目录,相对地址
../       表示上层目录,绝对地址
/         表示根目录,绝对地址

__dirname表示当前文件在系统中的绝对路径,比如我在D:\projects\vue-cli-learning文件夹下新建了一个test.js文件:

console.log(__dirname)

在Node环境下运行这个文件输出结果就是:

D:\projects\vue-cli-learning

path.resolve的目的是用来将相对路径转为绝对路径,接受多册参数,一次表示要进入的路径,直到最后一个参数为止。除了根目录,该方法的返回值都不带尾部的斜杠

// 实例
path.resolve('foo/bar', '/tmp/file/', '..', 'a/../subfile')

上面代码的实例,执行效果类似下面的命令。

$ cd foo/bar
$ cd /tmp/file/
$ cd ..
$ cd a/../subfile
$ pwd

比如,在刚才的test.js中打印:

const path = require('path');
console.log(path.resolve(__dirname, 'a'));
console.log(path.resolve(__dirname, '../a'));

输出的结果就是两个路径:

D:\projects\vue-cli-learning\a
D:\projects\a

打包路径的配置

在处理字体文件的url-loader的配置选项中:

name: utils.assetsPath('fonts/[name].[hash:7].[ext]')

规定了Webpack打包后生成的资源名称和路径,其中,utils.assetsPath规定了跨系统平台输出文件路径,并且和环境变量相关:

exports.assetsPath = function (_path) {
  const assetsSubDirectory = process.env.NODE_ENV === 'production'
    ? config.build.assetsSubDirectory
    : config.dev.assetsSubDirectory

  return path.posix.join(assetsSubDirectory, _path)
}

在生产环境下的config.build.assetsSubDirectory配置实在/config/index.js中:

build: {
  // Template for index.html
  index: path.resolve(__dirname, '../dist/index.html'),
  
  // Paths
  assetsRoot: path.resolve(__dirname, '../dist/'),
  assetsSubDirectory: 'static',
  assetsPublicPath: '/',
  
  // ... 其他
}

其中,

index是生成的index.html在本机的地址,现在的配置下,生成的index文件会位于D:\projects\vue-cli-learning\dist\中(由path.resolve转换而来)

assetsRoot指明了构建后的资源的路径,Webpack会将所有打包后的资源(包括index.html在内都放到这个文件夹下

assetsSubDirectory是打包后的资源目录,除了index.html之外的所有模块都会放到这个文件夹中,当前配置后,所有的资源文件都会打包在D:\projects\vue-cli-learning\dist\static

assetsPublicPathstatic资源文件夹相对于HTTP服务器运行时的路径,比如我利用http模块构建了一个简单的静态服务器:

npx http-server -a 127.0.0.1 -p 7070

这个时候服务器运行的URL是localhost:7070/

当前目录的情况是这样:

Vue提高18 更换打包文件路径_第1张图片

如果我在App.vue中引入的字体文件路径是./assets/font/d.ttf),在打包之后首先由对应的url-loader处理,生成的字体文件将位于/dist/static/fonts中,打包后静态服务器请求的字体地址是:http://127.0.0.1:7070/static/fonts/d.d30126a.ttf

明白这些选项都是干什么的后,就可以更改了

(1)更改打包后的文件路径,更改index选项assetsRoot选项,比如更改为:

build: {
  // Template for index.html
  index: path.resolve(__dirname, '../dist/test/index.html'),
  
  // Paths
  assetsRoot: path.resolve(__dirname, '../dist/test/'),
  assetsSubDirectory: 'static',
  assetsPublicPath: '/',
  
  // ... 其他
}

这时候打包后文件将是这样的结构:

Vue提高18 更换打包文件路径_第2张图片

(2)更改打包后静态资源所在目录(同时对资源的请求也会更改,因为打包后内联的URL地址也由url-loader一并改变了

更改为:

build: {
  // Template for index.html
  index: path.resolve(__dirname, '../dist/index.html'),
  
  // Paths
  assetsRoot: path.resolve(__dirname, '../dist/'),
  assetsSubDirectory: 'static/hello/',
  assetsPublicPath: '/',
  
  // ... 其他
}

此时打包生成的目录:

Vue提高18 更换打包文件路径_第3张图片

发出的获取字体的网络请求的URL为http://127.0.0.1:7070/static/hello/fonts/d.d30126a.ttf

(3) 更改HTTP服务器获取静态资源的路径

这个一直把我搞混了,在默认的配置情况下是去网站的根目录下去寻找assetsSubDirectory中规定的资源目录,比如http://127.0.0.1:7070/static/fonts/d.d30126a.ttf

但是如果资源不是在根目录下呢,比如需要通过http://127.0.0.1:7070/ok/static/fonts/d.d30126a.ttf来请求字体时,就需要改动assetsPublicPath了,此时的配置:

build: {
  // Template for index.html
  index: path.resolve(__dirname, '../dist/index.html'),
  
  // Paths
  assetsRoot: path.resolve(__dirname, '../dist/'),
  assetsSubDirectory: 'static/',
  assetsPublicPath: '/ok/',
  
  // ... 其他
}

这个时候打包后的目录没有变化,但是请求字体的URL就变成了http://127.0.0.1:7070/ok/static/fonts/d.d30126a.ttf

如果要将assetsPublicPath改为./会发生什么呢?请求字体的URL发生了变化

这是因为./是相对地址,相对发出请求的文件所在的木而言的,这个请求是谁发出的呢?是打包后的CSS文件发出的

Vue提高18 更换打包文件路径_第4张图片

转换为绝对路径就是/static/css/,然后再这个目录下再去寻找资源目录,所以请求的URL是http://127.0.0.1:7070/static/css/static/fonts/d.d30126a.ttf,这肯定不是我们想要的

所以在更改assetsPublicPath时,尽量采用绝对地址,从服务器的根节点域名触发,定位资源文件,不容易发生错误。

总结

回到初衷,本意只是简单的更改打包后的文件路径,想要打包在/dist/project中,只需要简单的更改index选项和assertsRoot即可

build: {
  index: path.resolve(__dirname, '../dist/project/index.html'),
  assetsRoot: path.resolve(__dirname, '../dist/project/'),
}

这两项只会影响打包后在本地的路径,而assetsSubDirectory会影响请求和本地打包后路径,assetsPublicPath只会影响上线后发送请求的路径。

简单的一点改动,引出了一堆东西要学习。

参考

  • webpack学习笔记-2-file-loader和url-loader@CSDN
  • Path模块@JavaScript标准参考教程
  • webpack再入门,说一下那些不入流的知识点@segmentfault
  • webpack的3个路径配置项@博客园

你可能感兴趣的:(Vue)