webpack 项目访问静态资源

使用 webpack dev serve 启动 react 项目后,发现无法使用 http://localhost:8080/1.png 访问到项目的 /static 目录下的 1.png 文件。我的 webpack-dev.js 配置如下:

javascript 复制代码
const webpack = require('webpack')
const webpackMerge = require('webpack-merge')
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
const baseWebpackConfig = require('./webpack.config.base')
const proxy = require('../proxy/index.js')
const path = require('path')
const smp = new SpeedMeasurePlugin()

const config = webpackMerge.merge(baseWebpackConfig, {
  mode: 'development', // 模式 默认两种 production development
  devtool: 'cheap-module-eval-source-map',
  plugins: [
    new webpack.HotModuleReplacementPlugin() // 热更新插件
  ],
  devServer: { // 开发服务器配置
    hot: true,
    port: 8080,
    open: false,
    quiet: false,
    inline: true,
    stats: 'errors-only',
    overlay: false,
    clientLogLevel: 'silent',
    compress: true,
    // contentBase: path.join(__dirname, 'dist'),
    contentBase: path.join(__dirname, '../static'), // 设置开发服务器根目录
    proxy: {
      '/': {
        bypass: function (req, res, proxyOptions) {
          return `/index.html`
        }
      },
      ...proxy
    }
  }
})

module.exports = config

发现是 proxy 的配置下 把 访问 / 的路径全部拦截到 /index.html 下了,所以访问不到 /static 目录下的静态资源。

解决方案

改一下 proxy 的逻辑即可,修改后的 webpack-dev.js 配置:

javascript 复制代码
const webpack = require('webpack')
const webpackMerge = require('webpack-merge')
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
const baseWebpackConfig = require('./webpack.config.base')
const proxy = require('../proxy/index.js')
const path = require('path')
const smp = new SpeedMeasurePlugin()

const config = webpackMerge.merge(baseWebpackConfig, {
  mode: 'development', // 模式 默认两种 production development
  devtool: 'cheap-module-eval-source-map',
  plugins: [
    new webpack.HotModuleReplacementPlugin() // 热更新插件
  ],
  devServer: { // 开发服务器配置
    hot: true,
    port: 8080,
    open: false,
    quiet: false,
    inline: true,
    stats: 'errors-only',
    overlay: false,
    clientLogLevel: 'silent',
    compress: true,
    // contentBase: path.join(__dirname, 'dist'),
    contentBase: path.join(__dirname, '../static'), // 设置开发服务器根目录
    proxy: {
      '/': {
        bypass: function (req, res, proxyOptions) {
          // 如果请求的是以 /static/resources 开头的路径,不做重定向,直接返回 null
          if (req.url.startsWith('/resources')) {
            return null;  // 不重定向,继续处理静态资源
          }
          return `/index.html`
        }
      },
      ...proxy
    }
  }
})

module.exports = config

相关文档可以参考 webpack 官网 - proxy


继续展开

我发现我执行 npm run build 无法将 我的react项目跟目录下的 /static/resources/pdf/ 资源打包到 dist 目录中。

解决办法:

安装 copy-webpack-plugin@6.0.0 插件, 这个版本适配 webpack@4.41.5 这个版本,已经测试可用。

bash 复制代码
npm install copy-webpack-plugin@6.0.0

然后再 webpack.base.js 配置:

bash 复制代码
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
plugins: [
    new CopyWebpackPlugin({
      patterns: [
        { from: 'static/resources/pdf', to: 'static/resources/pdf' }
      ]
    })
  ]
}

手动指定要复制的资源,这样执行 npm run build 之后就能将 /static/resources/pdf下的文件打包到 /dist/static/resources/pdf 目录下了。


继续展开

我有一个需求就是要将文档放在项目目录中,然后用户点击下载按钮,就找到项目中的对应文件下载。

代码如下:

javascript 复制代码
  function createAndRemove(url, fileName) {
  	// 创建 a 标签
    var link= document.createElement('a');
    // 下载内容转变成blob地址
    link.href = process.env.INTERFACE_DOCUMENT + "a.pdf";
    link.download = fileName;
    // 触发点击
    document.body.appendChild(link);
    eleLink.click();
    // 然后移除
    document.body.removeChild(link);
  }

为什么要用 process.env.INTERFACE_DOCUMENT 这个变量?

因为项目部署在本地(通过 npm start 启动) 和 部署到线上路径可能会不一样。

a.pdf 文件在项目的根目录下的 /static/resources/pdf/ , 访问路径为 http://localhost:8080/resources/pdf/a.pdf

项目打包后, a.pdf 会被打包到 /dist/static/resources/pdf/ , 部署到线上后,使用的 nginx 部署项目, nginx 的配置指定 dist 为根目录,

nginx.conf 配置如下

bash 复制代码
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;
    
    include /etc/nginx/conf.d/*.conf;

    server {
        listen       80;
        listen       [::]:80;
        server_name  _;
        #root         /usr/share/nginx/html;
	root 	     /project;

	location / {
		root /dist;
		index	 index.html index.htm;
		try_files	 $uri $uri/ /index.html;  # 解决页面路由问题,刷新页面返回 404
	}

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }
}

dist 目录结构为

bash 复制代码
|- dist
|-----static
|---------- img
|---------- css
|---------- js
|---------- resources
|-----------------pdf 

此时线上访问 a.pdf 的路径为 http://ip:port/static/resources/pdf/a.pdf

所以才会有根据环境变量来获取 URL的这段代码 process.env.INTERFACE_DOCUMENT。

.env.development 文件

bash 复制代码
INTERFACE_DOCUMENT=/resources/pdf/

.env.production 文件

bash 复制代码
INTERFACE_DOCUMENT=/static/resources/pdf/

这样配置完后,在本地和在线上就都能够正常下载了。

注意:如果你的文件名为中文,部署到 linux 中,中文可能会乱码,会导致找不到文件,所以最好使用英文文件名。

相关推荐
恋猫de小郭26 分钟前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
崔庆才丨静觅7 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60618 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了8 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅8 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅9 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment9 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端