webdiscus / pug-plugin

Renders Pug template to HTML or template function. Resolves source files of scripts, styles, images in Pug . Uses Pug template as entry point.
https://webdiscus.github.io/pug-plugin/hello-world
ISC License
74 stars 8 forks source link

Can I choose different outputPath of specific file by extension? #53

Closed ltsfran closed 1 year ago

ltsfran commented 1 year ago

I want to know if is possible to set different outputPath of specific files. I'm using in my project PugJS, StylusJS, and Typescript. I've configured the output.path to dist directory, so now all files render inside it.

module.exports = {
  mode,
  watch: !isProduction,
  entry: WebpackUtil.filesToCompileSync('pug/modules', /\.pug$/),
  output: {
    path: path.resolve(__dirname, 'dist'),
    publicPath: '/',
    clean: true
  },
  resolve: {
    extensions: ['.ts', '.js'],
  },
  plugins: [
    new PugPlugin({
      pretty: !isProduction,
      filename: '[name].phtml',
      modules: [
        {
          test: /\.(css|styl)$/,
          outputPath: path.resolve(__dirname, 'other/path/')
        }
      ],
      css: {
        filename: 'css/[name].css',
        outputPath: path.join(__dirname, 'test')
      },
      js: {
        filename: 'js/[name].js'
      }
    })
  ],
  module: {
    rules: [
      {
        test: /\.pug$/,
        loader: PugPlugin.loader
      },
      {
        test: /\.(css|styl)$/,
        use: ['css-loader', 'stylus-loader']
      },
      {
        test: /\.ts$/,
        loader: 'ts-loader'
      }
    ]
  }
}

I've seen in your documentation that I can configure outputPath from specific directory, something like this:

const PugPlugin = require('pug-plugin');
module.exports = {
  plugins: [
    new PugPlugin({
      modules: [
        {
          test: /fonts\/.+\.svg$/,
          outputPath: path.join(__dirname, 'dist/some/other/path/'),
        },
      ],
    }),
  ],
};

I want to do this:

html: application/modules/...
css: css/modules/...
js: js/modules/...

This is my public repo if you want to see it https://github.com/ltsfran/example-legacy-webpack

webdiscus commented 1 year ago

Hello @ltsfran,

Yes, it's possible, but currently works for Pug files only. It must works for all modules, but seems not work for styles. I will fix this issue.

Thank you for issue report.

ltsfran commented 1 year ago

Thank you, I'll try another different way

webdiscus commented 1 year ago

Thank you, I'll try another different way

Later today I will release a fixed version.

webdiscus commented 1 year ago

@ltsfran

Important: the outputPath for pug, js and css must be under same public output path.

The public path is the root web path for server. All public assets: html, js, css must be in this public path, e.g. path.join(__dirname, 'dist/').

You can define paths in filename option:

const PugPlugin = require('pug-plugin');
module.exports = {
  plugins: [
    new PugPlugin({
      filename: 'application/modules/[name].html', // => dist/application/modules/*.html,
      js: {
        filename: 'js/modules/[name].js', //  => dist/js/modules/*.js, where * is source filename
      },
      css: {
        filename: 'css/modules/[name].css',  //  => dist/css/modules/*.css, where * is source filename
        // outputPath: path.join(__dirname, 'test') // WRONG path, because is outer the `dist/`
      },
    }),
  ],
};

You will define a path outer web root path, it not works:

dist/ - web root path
dist/index.html (all js and css are loaded with relative by dist/ path)
dist/css/styles.css
dist/js/scripts.js

test/ - this is outer the web root path, this path is not available in dist/index.html 
ltsfran commented 1 year ago

@webdiscus the problem that I have: entries:

webdiscus commented 1 year ago

are all these files in the same directory?

public/html/modules/landing/views/index.html
public/css/modules/landing/index.css
public/js/modules/landing/index.js

then in the html/modules/landing/views/index.html file the assets have paths:

<link href="/css/modules/landing/index.css" rel="stylesheet">
<script src="/js/modules/landing/index.js" defer="defer"></script>

It is correct?

webdiscus commented 1 year ago

@ltsfran

dynamically directories can be under same output path. You can generate dynamically directories using the filename as function, e.g.:

filename: (pathData) => {
  const sourceFile = pathData.filename;                       // => /path/to/src/pages/about.pug
  const relativeFile = path.relative(sourcePath, sourceFile); // => pages/about.pug
  const { dir, name } = path.parse(relativeFile);             // dir: 'pages', name: 'about'
  return `${dir}/${name}.html`;                               // => dist/pages/about.html
};
ltsfran commented 1 year ago

I'm going to test that. Now It works with pug files, I want to do this with .styl and .ts files

ltsfran commented 1 year ago

With stylus files it doesn't work because pathData.filename doesn't exist

webdiscus commented 1 year ago

@ltsfran

update please to v4.7.0. I have added the outputPath property to js and css options.

new PugPlugin({
    js: {
      verbose: true, // display output info
      filename: '[name].[contenthash].js',
      outputPath: 'assets/js/', // relative or absolute path
    },
    css: {
      verbose: true, // display output info
      filename: '[name].[contenthash].css',
      outputPath: path.join(__dirname, 'assets/css/'), // relative or absolute path
    },
  }),

P.S.: You can now use the js.filename and css.filename as function. The pathData argument contains the filename property (fixed in new ver).

ltsfran commented 1 year ago

Thanks so much, Now I can access to filename property for my css files.

webdiscus commented 1 year ago

@ltsfran

is your problem solved? Can be closed the issue?

ltsfran commented 1 year ago

Yes @webdiscus , thanks so much