1

PUG 需要图像(webpack)

pug + webpack 中的图像处理问题。在 PUG 的早期,我不通过 loader 处理图片。我使用了 WebpackCopyPlugin,并写了绝对路径。

像那样:

- let imgPath = '/assets/img/'
img(src=imgPath + 'icons/logo/boto.agency.b.svg')

当我构建项目时,WebpackCopyPlugin 复制了所有图片,使用正确的路径编译了 pug,一切正常。现在我需要通过 Loader 处理图片。根据文档,我需要这样编写路径:img (src = require ('./img.png')) 但通常它不能正常工作。我发现了几个场景。在 src/assets/img 文件夹中有几张图片。

1.

img(src=require('../../../../assets/img/1-1.png'))

或者

img(src=require(`@img/1-1.png`)) 
// '@img': path.resolve(__dirname, '../../src/assets/img/')

一切正常,在组装过程中我们有 1 个文件 1-1.png。这里我没有在 require 中使用变量,因此这些选项不适合

2.开始使用变量:

- let fileName = '1-1.png'

img(src=require(`@img/${fileName}`))

或者

img(src=require(`../../../../assets/img/${fileName}`))

或者

img(src=require(`@img/`+fileName))

或使用 mixin

在开发模式下一切都很好。项目构建后,发生以下情况 - 文件加载器从文件夹中复制所有文件,尽管我只指定了 1。它是这样发生的:

file-loader test: /\.(png|jpg|gif|svg)$/,
  • 资产
    • 图像
      • 1-1.png
      • 2-2.jpg
      • 图标
        • 3.svg
      • 图片
        • 3.png
        • 3.jp2
        • 3.jxr

项目构建后,文件夹 public(dist)/assets/img 中将包含除 3.jp2 3.jxr 之外的所有文件(3.png 和 3.svg 也将被复制,即使它们在文件夹中)。这个选项也不合适。我只想接收我指定的那些文件。

3.开始实验

- let fileName = 'img/1-1.png'
img(src=require(`../../../../assets/${fileName}`))

我在开发中遇到错误并同时构建:

throw new Error('回调已被调用。'); ^ 错误:回调已被调用。

- let fileName = 'img/1-1.png'
// '@': path.resolve(__dirname, '../../src/assets/')
img(src=require(`@/${fileName}`))

也是一个错误

4.

- let fileName = '1-1.png'
- let basePath = '../../../../assets/img/'
- let path = basePath+fileName

img(src=require(path))

或者

- let aliasPath = '@/img/'
- let path = aliasPath+fileName
img(src=require(path))

错误:找不到模块“../../../../assets/img/1-1.png”

- let fileName = 'img/1-1.png'
- let basePath = '../../../../assets/'
- let path = fileName+basePath2
img(src=require(path))

错误:找不到模块“../../../../assets/img/1-1.png”

对于任何文件加载器配置,这完全取决于我是否在 equire 中使用变量

问题是什么?

我的 webpack 配置:

/* Base config:
   ========================================================================== */
const webpack = require('webpack');
const path = require('path');
const fs = require('fs');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {VueLoaderPlugin} = require('vue-loader');
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
// Main const. Feel free to change it
const isDev = process.env.NODE_ENV === 'development';
const isProd = !isDev;
const PATHS = {
  src: path.join(__dirname, '../../src'),
  dist: path.join(__dirname, (isProd ? '../../public' : '../../dist')),
  webpack: path.join(__dirname, '../../webpack'),
  assets: 'assets/',
};

const fileName = ext => isDev ? `[name].${ext}` : `[name].[hash].${ext}`
const plugins = (type) => {
  const base = [
    new VueLoaderPlugin(),
    new MiniCssExtractPlugin({
      filename: `${PATHS.assets}css/${fileName('css')}`,
    }),
    new webpack.ProvidePlugin({
      '$': 'jquery',
      'jQuery': 'jquery',
      'window.jQuery': 'jquery',
    }),
    new CopyWebpackPlugin({
      patterns: [
        //{from: `${PATHS.src}/${PATHS.assets}img`, to: `${PATHS.assets}img`},
        {from: `${PATHS.src}/${PATHS.assets}fonts`, to: `${PATHS.assets}fonts`},
        {from: `${PATHS.src}/pages/php`, to: ``},
        {from: `${PATHS.src}/static`, to: ''},
      ]
    }),
    new CleanWebpackPlugin(),
  ];
  switch (type) {
    case 'html': {
      const PAGES_DIR = `${PATHS.src}/pages`;
      const PAGES = fs
        .readdirSync(PAGES_DIR)
        .filter((fileName) => fileName.endsWith('.html'));
      base.push(
        ...PAGES.map(
          (page) =>
            new HtmlWebpackPlugin({
              template: `${PAGES_DIR}/${page}`,
              filename: page,
            }),
        ),);
      break;
    }

    case 'pug': {
      const PAGES_DIR = `${PATHS.src}/pages/pug/includes/pages`;
      const PAGES = fs
        .readdirSync(PAGES_DIR)
        .filter((fileName) => fileName.endsWith('.pug'));
      base.push(
        ...PAGES.map(
          (page) =>
            new HtmlWebpackPlugin({
              template: `${PAGES_DIR}/${page}`,
              filename: (page === 'index.pug' || page === '404.pug' ?
                page.replace(/\.pug/, '.html') :
                `${page.split('.')[0]}/index.html`),
            }),
        ),);
      break;
    }
  }
  const PAGES_PHP = fs
    .readdirSync(PATHS.src)
    .filter((fileName) => fileName.endsWith('.php'));
  base.push(
    ...PAGES_PHP.map(
      (page) =>
        new HtmlWebpackPlugin({
          template: `${PATHS.src}/${page}`,
          filename: `${page}`,
          inject: false,
        }),
    ),)
  return base
}


module.exports = {
  externals: {
    paths: PATHS,
  },
  entry: {
    app: ['@babel/polyfill', PATHS.webpack]
    // module: `${PATHS.src}/your-module.js`,
  },
  output: {
    filename: `${PATHS.assets}js/${fileName('js')}`,
    path: PATHS.dist,
    publicPath: isDev ? '/' : '/',

  },
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendor: {
          name: 'vendors',
          test: /node_modules/,
          chunks: 'all',
          enforce: true,
        },
        // css: {
        //   name: 'css',
        //   test: /\.css$/,
        //   chunks: 'all',
        //   enforce: true,
        // },
        // scss: {
        //   name: 'scss',
        //   test: /\.scss$/,
        //   chunks: 'all',
        //   enforce: true,
        // },
      },
    },
  },
  devtool: isDev ? 'source-map' : 'eval',
  module: {
    rules: [
      // TypeScript
      {
        test: /\.ts$/,
        exclude: /node_modules|vue\/src/,
        loader: 'ts-loader',
        options: {
          appendTsSuffixTo: [/\.vue$/],
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          presets: [
            '@babel/preset-env'
          ]
        }
      },
      {
        test: /\.pug$/,
        oneOf: [
          {
            resourceQuery: /^\?vue/,
            use: ['pug-plain-loader'],
          },
          {
            use: ['pug-loader'],
          }
        ],
      },
      {
        // Vue
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          loader: {
            scss: 'vue-style-loader!css-loader!sass-loader',
          },
          postcss: {
            config: {
              path: PATHS.webpack,
            },
          },
        },
      },
      {
        // Fonts
        test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
        loader: 'file-loader',
        options: {
          name: `[name].[ext]`,
          outputPath: '/assets/fonts/'
        },
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
              esModule: false,
               name: '[name].[ext]',
              outputPath: `${PATHS.assets}/img`,
             //publicPath: `/${PATHS.assets}img`,
            },
          },
        ],

      },
      {
        // scss
        test: /\.scss$/,
        use: [
          'style-loader',
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {sourceMap: true},
          },
          {
            loader: 'postcss-loader',
            options: {
              sourceMap: true,
              config: {path: `${PATHS.webpack}/postcss.config.js`},
            },
          },
          {
            loader: 'sass-loader',
            options: {
              sourceMap: true,
            },
          },
          {
            loader: 'sass-resources-loader',
            options: {
              resources: [
                './src/assets/scss/core/base.scss',
              ],
            },
          },
        ],
      },
      {
        // css
        test: /\.css$/,
        use: [
          'style-loader',
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader',
            options: {sourceMap: true},
          },
          {
            loader: 'postcss-loader',
            options: {
              sourceMap: true,
              config: {path: `${PATHS.webpack}/postcss.config.js`},
            },
          },
        ],
      },
      // {
      //   test: /\.(html)$/,
      //   use: [
      //     {
      //       loader: 'html-loader',
      //       // options: {
      //       //   minimize: {
      //       //     removeComments: true,
      //       //     collapseWhitespace: false,
      //       //   },
      //       // },
      //     },
      //   ],
      // },
    ],
  },
  resolve: {
    alias: {
      '~': PATHS.src,
      'vue$': 'vue/dist/vue.js',
      '@': path.resolve(__dirname, '../../src'),
      '@img': path.resolve(__dirname, '../../src/assets/img/'),
    },
    extensions: ['.tsx', '.ts', '.js'],
  },

  plugins: plugins('pug'),


};
4

0 回答 0