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 中,中文可能会乱码,会导致找不到文件,所以最好使用英文文件名。

相关推荐
子兮曰1 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰1 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万1 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝1 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95271 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大1 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师1 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学1 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端