Webpack 中 publicPath 在 Nginx 部署的使用

367 阅读3分钟

output.publicPath 配置发布到线上资源的 URL 前缀,为string 类型。 默认值是空字符串 '',即使用相对路径。

对于按需加载(on-demand-load)或加载外部资源(external resources)(如图片、文件等)来说,output.publicPath 是很重要的选项。 如果指定了一个错误的值,则在加载这些资源时会收到 404 错误。

WebPack 官网

此选项指定在浏览器中所引用的「此输出目录对应的公开 URL」。publicPath 支持下列配置方式之一

  1. "auto"
  2. 相对 URL(relative URL) 会被相对于 HTML 页面(或 <base> 标签)解析。
  3. 相对于服务的 URL(Server-relative URL)
  4. 相对于协议的 URL(protocol-relative URL) 或绝对 URL(absolute URL) 也是可能用到的,或者有时必须用到,例如:当将资源托管到 CDN 时。

publicPath 无论是相对路径还是绝对路径,尾部都要携带斜杠/

publicPath 配置示例:

module.exports = {
  //...
  output: {
    // 1. "auto"
    publicPath: 'auto', // It automatically determines the public path from either `import.meta.url`, `document.currentScript`, `<script />` or `self.location`.
    // 2. 相对 URL(relative URL) 会被相对于 HTML 页面(或 `<base>` 标签)解析。
    publicPath: 'assets/', // 相对于 HTML 页面
    publicPath: '../assets/', // 相对于 HTML 页面
    publicPath: '', // 相对于 HTML 页面(目录相同)
    // 3. 相对于服务的 URL(Server-relative URL)
    publicPath: '/assets/', // 相对于服务(server-relative)
    // 4. 相对于协议的 URL(protocol-relative URL) 或绝对 URL(absolute URL)
    publicPath: 'https://cdn.example.com/assets/', // CDN(总是 HTTPS 协议)
    publicPath: '//cdn.example.com/assets/', // CDN(协议相同)
  },
};

publicPath 各种配置方式

auto

您可能事先不知道publicPath是什么,webpack可以通过从import.meta.url、document.currentScript、script.src或self.location等变量中确定公共路径来自动为您处理它。您需要的是将output.publicPath设置为"auto"。

相对 URL

module.exports = {
  //...
  output: {
    publicPath: 'hsy/', // 相对于 HTML 页面,等价于 ./hsy/
    publicPath: '../hsy/', // 相对于 HTML 页面
    publicPath: '', // 相对于 HTML 页面(目录相同)
  },
};

打包结果: image.png

相对于服务的 URL

module.exports = {
  //...
  output: {
      publicPath: '/hsy/', // 相对于服务(server-relative)
  },
};

打包结果: image.png 这种配置方式当浏览器引入静态资源时是相对于当前 HTML 页面的 URL,现在以我的打包构建结果为例来看看部署到 Nginx 服务器上后的访问过程。 打包结果 dist 目录结构如下: image.png

资源目录在网站根目录下

Nginx 配置:

server {
    listen 80;
    server_name example.com;
    
    location / {
        root /usr/local/nginx/html; # HTML 文件位置,webpack 中 publicPath 配置中 "/hsy/",第一个 "/" 就对应 nginx 中当前根目录
        try_files $uri $uri/ /index.html;
    }
    
    
    # 不需要特殊配置 /hsy/,因为资源就在根目录下的 hsy 文件夹中
    # Nginx 会自动处理 /hsy/ 请求到 /var/www/html/hsy/ 目录
}

有一个问题需要说明:Nginx网站根目录和Linux根目录的区别?\color{red}{有一个问题需要说明:Nginx 网站根目录和 Linux 根目录的区别?}

Linux 根目录:指的是 操作系统的目录树起点 /

Nginx 网站根目录

  • Nginx 配置文件里定义的项目访问入口目录,通过 rootalias 指令配置。

  • 当浏览器请求静态资源时,Nginx 会从这个目录去查找文件。

  • 默认在安装好 Nginx 后,配置是:

    root /usr/local/nginx/html;
    
  • 意味着:

    • 访问 http://服务器IP/ → 对应 /usr/local/nginx/html/index.html
    • 访问 http://服务器IP/css/style.css → 对应 /usr/local/nginx/html/css/style.css

👉 Nginx 网站根目录是文件映射关系,不是系统根目录

Nginx 服务器目录: image.png 当我们打开浏览器访问部署后的页面时,首先加载 <script defer="defer" src="/hsy/js/runtime_2868c4aa.js"></script>中 url 为 /hsy/js/runtime_2868c4aa.js 的js 文件,服务器会返回 root /usr/local/nginx/html 下的 hsy 目录下对应的资源。

资源目录在任意位置(推荐)

这是更灵活和常见的做法。您可以将资源放在服务器的任何位置,然后通过 Nginx 配置将 /hsy/ URL 路径映射到该位置。

Nginx 服务器目录:

/usr/local/nginx/
├── html/                 # 网站根目录
│   └── index.html        # HTML 入口文件
└── static-assets/        # 静态资源目录(可以放在任何位置)
    └── hsy/        # 您的构建输出
        ├── common_5cedef9f.js
        ├── import_another_cee62f07.js
        ├── main_55ccf2ef.js
        ├── import_another_cee62f07.js
        ├── runtime_2868c4aa.js
        └── vendors_a4eeeed2.js

Nginx 配置:

server {
    listen 80;
    server_name example.com;
    
    location / {
        root /usr/local/nginx/html; # HTML 文件位置,webpack 中 publicPath 配置中 "/hsy/",第一个 "/" 就对应 nginx 中当前根目录
        try_files $uri $uri/ /index.html;
    }
    
    location /hsy/ {
       alias /usr/local/nginx/static-assets/hsy/; # 资源实际存放位置
       expires 1y;
    }
}

将资源托管到 CDN

filename:'[name]_[chunkhash:8].js'
publicPath: 'https://cdn.example.com/assets/'

这时发布到线上的 HTML 在引入 JavaScript 文件时就需要:

<script src='https://cdn.example.com/assets/a_12345678.js'></script>