Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A valid query string passed to parseQuery should begin with '?' #46

Open
beeryukov opened this issue May 14, 2020 · 10 comments
Open

A valid query string passed to parseQuery should begin with '?' #46

beeryukov opened this issue May 14, 2020 · 10 comments

Comments

@beeryukov
Copy link

beeryukov commented May 14, 2020

ejs-compiled-loader version is 3.0.0
"webpack" is "4.43.0",
"webpack-cli" is "3.3.11"
Get the following error when building:

Module build failed (from ./node_modules/ejs-compiled-loader/index.js):
Error: A valid query string passed to parseQuery should begin with '?'
at Object.parseQuery (/media/data/web/node_modules/ejs-compiled-loader/node_modules/loader-utils/lib/parseQuery.js:13:11)
at Object.module.exports (/media/data/web/node_modules/ejs-compiled-loader/index.js:15:102)

@bazilio91
Copy link
Owner

Can you provide your loader rule from webpack config?

@SamBroner
Copy link

SamBroner commented May 21, 2020

I also have this issue, I can resolve it by setting var query = {};

My loader rule is below.

            {
                test: /\.ejs$/, 
                use: {
                  loader: 'ejs-compiled-loader',
                  options: {
                    htmlmin: true,
                    htmlminOptions: {
                      removeComments: true
                    }
                  }
                }
              }

Here are my dev dependencies

    "@types/node": "^13.13.4",
    "copy-webpack-plugin": "^5.1.1",
    "css-loader": "^3.5.3",
    "ejs-compiled-loader": "^3.0.0",
    "eslint": "^6.8.0",
    "file-loader": "^6.0.0",
    "html-webpack-plugin": "^4.2.0",
    "image-webpack-loader": "^6.0.0",
    "mini-css-extract-plugin": "^0.9.0",
    "style-loader": "^1.2.0",
    "ts-loader": "^7.0.1",
    "typescript": "^3.8.3",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3"

@SamBroner
Copy link

@beeryukov, I believe I resolved this for myself.

I was using the HtmlWebpackPlugin like this:

        new HtmlWebpackPlugin({
            template: "!!ejs-compiled-loader!./public/index.ejs",
            templateParameters: {
                posts: postTemplates,
                post: false
            }
        }),

However, you can also just set the loader as a rule in your loader, HtmlWebpackPlugin will pick up this rule. So you can change the Html Webpack Plugin to not use the !!ejs-compiled-loader! syntax

            {
                test: /\.ejs$/, 
                use: {
                  loader: 'ejs-compiled-loader',
                  options: {
                    htmlmin: true,
                    htmlminOptions: {
                      removeComments: true
                    }
                  }
                }
              }

&

        new HtmlWebpackPlugin({
            template: "./public/index.ejs",
            templateParameters: {
                posts: postTemplates,
                post: false
            }
        }),

Kind of confusing between the READMEs, but solved my issue.

@ZacxDev
Copy link

ZacxDev commented Jun 7, 2020

I also had this issue, I resolved it by changing my webpack rule from:

    rules: [
    {
      test: /\.ejs$/,
      use: 'ejs-compiled-loader'
    }]

to:

  rules: [
    {
      test: /\.ejs$/,
      use: {
        loader: 'ejs-compiled-loader',
        options: {
          htmlmin: true,
          htmlminOptions: {
            removeComments: true
          }
        }
      }
    }]

It seems ejs-compiled-loader does not like options being undefined.

@songxingguo
Copy link

I also had this issue, but It can't be solved by the above method, So someone can help me, thank you.

@ZacxDev
Copy link

ZacxDev commented Jun 13, 2020

I also had this issue, but It can't be solved by the above method, So someone can help me, thank you.

Can you share your ejs webpack config rule?

@songxingguo
Copy link

songxingguo commented Jun 14, 2020

I also had this issue, but It can't be solved by the above method, So someone can help me, thank you.

Can you share your ejs webpack config rule?
webpack.config.js

const path = require('path');
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MinCssExtractPlugin = require("mini-css-extract-plugin");   // 将css代码提取为独立文件的插件
const MediaQueryPlugin = require('media-query-plugin');

module.exports = {
  mode: 'production',
  entry: [
    './src/index.js'
  ],
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [{
      test: /\.s[ac]ss$/i,
      use: [
        {
          loader: MinCssExtractPlugin.loader,  // 将处理后的CSS代码提取为独立的CSS文件,可以只在生产环境中配置,但我喜欢保持开发环境与生产环境尽量一致
          options: {
            publicPath: '/assets/',
            // only enable hot in development
            hmr: true,
            // if hmr does not work, this is a forceful method.
            reloadAll: true,
          },
        },
        'css-loader',  // CSS加载器,使webpack可以识别css文件
        MediaQueryPlugin.loader,
        'postcss-loader', // 承载autoprefixer功能,为css添加前缀
        'sass-loader', // Compiles Sass to CSS
      ],
    },
      {
        test: /\.css$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[hash:8].[ext]',
            outputPath: 'assets/',
            publicPath: './assets/'
          }
        },
          'extract-loader',
          'css-loader',
          'postcss-loader']
      },
      {
        test: /\.(jpg|png|gif|svg)$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name].[hash:8].[ext]',
            outputPath: 'assets/',
            publicPath: './assets/'
          }
        }
      },
      {
        test: /\.ejs$/,
        use: {
          loader: 'ejs-compiled-loader',
          options: {
            htmlmin: true,
            htmlminOptions: {
              removeComments: true
            }
          }
        }
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin({
    template: 'src/index.ejs',
    inject: true,
    minify: {
      collapseWhitespace: true
    }
  }),
    new webpack.HotModuleReplacementPlugin(),
    new MinCssExtractPlugin(),
    new MediaQueryPlugin({
      include: [
        'style',
      ],
      queries: {
        'print': 'print',
        'not print': 'not-print'
      }
    })
  ],
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    overlay: true,
    port: 4550,
    open: true,
    hot: true
  }
};

package.json

{
  "name": "resume",
  "version": "1.0.0",
  "description": "个人简历",
  "main": "index.js",
  "repository": "",
  "author": "",
  "license": "MIT",
  "scripts": {
    "start": "webpack-dev-server --mode=development",
    "build": "webpack --mode=production"
  },
  "devDependencies": {
    "@babel/core": "^7.10.2",
    "@babel/preset-env": "^7.10.2",
    "autoprefixer": "^9.1.5",
    "babel-loader": "^8.1.0",
    "css-loader": "^1.0.0",
    "cssnano": "^4.1.0",
    "ejs-compiled-loader": "^3.0.0",
    "ejs-loader": "^0.5.0",
    "extract-loader": "^2.0.1",
    "file-loader": "^1.1.11",
    "html-webpack-plugin": "^3.2.0",
    "media-query-plugin": "^1.3.1",
    "mini-css-extract-plugin": "^0.9.0",
    "node-sass": "^4.14.1",
    "postcss-import": "^12.0.1",
    "postcss-loader": "^3.0.0",
    "postcss-px2rem-exclude": "0.0.6",
    "postcss-url": "^8.0.0",
    "px2rem-loader": "^0.1.9",
    "raw-loader": "^0.5.1",
    "sass-loader": "^8.0.2",
    "style-loader": "^1.2.1",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.11.0"
  },
  "dependencies": {
    "fs": "0.0.1-security",
    "lib-flexible": "^0.3.2"
  }
}

@songxingguo
Copy link

songxingguo commented Jun 18, 2020

I also had this issue, but It can't be solved by the above method, So someone can help me, thank you.

Can you share your ejs webpack config rule?
webpack.config.js

const path = require('path');
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MinCssExtractPlugin = require("mini-css-extract-plugin");   // 将css代码提取为独立文件的插件
const MediaQueryPlugin = require('media-query-plugin');

module.exports = {
  mode: 'production',
  entry: [
    './src/index.js'
  ],
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'bundle.js'
  },
  module: {
    rules: [{
      test: /\.s[ac]ss$/i,
      use: [
        {
          loader: MinCssExtractPlugin.loader,  // 将处理后的CSS代码提取为独立的CSS文件,可以只在生产环境中配置,但我喜欢保持开发环境与生产环境尽量一致
          options: {
            publicPath: '/assets/',
            // only enable hot in development
            hmr: true,
            // if hmr does not work, this is a forceful method.
            reloadAll: true,
          },
        },
        'css-loader',  // CSS加载器,使webpack可以识别css文件
        MediaQueryPlugin.loader,
        'postcss-loader', // 承载autoprefixer功能,为css添加前缀
        'sass-loader', // Compiles Sass to CSS
      ],
    },
      {
        test: /\.css$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[hash:8].[ext]',
            outputPath: 'assets/',
            publicPath: './assets/'
          }
        },
          'extract-loader',
          'css-loader',
          'postcss-loader']
      },
      {
        test: /\.(jpg|png|gif|svg)$/,
        use: {
          loader: 'file-loader',
          options: {
            name: '[name].[hash:8].[ext]',
            outputPath: 'assets/',
            publicPath: './assets/'
          }
        }
      },
      {
        test: /\.ejs$/,
        use: {
          loader: 'ejs-compiled-loader',
          options: {
            htmlmin: true,
            htmlminOptions: {
              removeComments: true
            }
          }
        }
      }
    ]
  },
  plugins: [new HtmlWebpackPlugin({
    template: 'src/index.ejs',
    inject: true,
    minify: {
      collapseWhitespace: true
    }
  }),
    new webpack.HotModuleReplacementPlugin(),
    new MinCssExtractPlugin(),
    new MediaQueryPlugin({
      include: [
        'style',
      ],
      queries: {
        'print': 'print',
        'not print': 'not-print'
      }
    })
  ],
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: true,
    overlay: true,
    port: 4550,
    open: true,
    hot: true
  }
};

package.json

{
  "name": "resume",
  "version": "1.0.0",
  "description": "个人简历",
  "main": "index.js",
  "repository": "",
  "author": "",
  "license": "MIT",
  "scripts": {
    "start": "webpack-dev-server --mode=development",
    "build": "webpack --mode=production"
  },
  "devDependencies": {
    "@babel/core": "^7.10.2",
    "@babel/preset-env": "^7.10.2",
    "autoprefixer": "^9.1.5",
    "babel-loader": "^8.1.0",
    "css-loader": "^1.0.0",
    "cssnano": "^4.1.0",
    "ejs-compiled-loader": "^3.0.0",
    "ejs-loader": "^0.5.0",
    "extract-loader": "^2.0.1",
    "file-loader": "^1.1.11",
    "html-webpack-plugin": "^3.2.0",
    "media-query-plugin": "^1.3.1",
    "mini-css-extract-plugin": "^0.9.0",
    "node-sass": "^4.14.1",
    "postcss-import": "^12.0.1",
    "postcss-loader": "^3.0.0",
    "postcss-px2rem-exclude": "0.0.6",
    "postcss-url": "^8.0.0",
    "px2rem-loader": "^0.1.9",
    "raw-loader": "^0.5.1",
    "sass-loader": "^8.0.2",
    "style-loader": "^1.2.1",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.11.0"
  },
  "dependencies": {
    "fs": "0.0.1-security",
    "lib-flexible": "^0.3.2"
  }
}

I solved this problem in other ways, This link

index.ejs:

<h1><%- require('./header.ejs')({ title: 'page name' }) -%></h1>
header.ejs:

<title><%= title %></title>

@TacticalCode
Copy link
Contributor

TacticalCode commented Jun 21, 2020

It's a bug, this.query is blindly passed to utils.parseQuery() which throws the error "A valid query string passed to parseQuery should begin with '?'" if the string representation of that object does not start with a '?'. See https://github.com/bazilio91/ejs-compiled-loader/blob/3.x/index.js#L15

Steps to reproduce:
Import without options object or query:
'!!ejs-compiled-loader!./path/to/template'
yields this error. Import with an undefined query:
'!!ejs-compiled-loader?!./path/to/template'
yields this error. Import with an empty object:
'!!ejs-compiled-loader?{}!./path/to/template'
yields no errors.

Debugging:
I used this code inserted before https://github.com/bazilio91/ejs-compiled-loader/blob/3.x/index.js#L15

        console.log("this.query is set");
        console.log("this.query is of type " + typeof this.query);
        if(typeof this.query === 'object') console.log("query is an 'object'");
        else console.log("query is not an 'object'");
      }
      else {
        console.log("no query");
      }

The output of that is
for !!ejs-compiled-loader!./path/to/tpl as well as !!ejs-compiled-loader?!./path/to/tpl

this.query is set
this.query is of type string

and for !!ejs-compiled-loader?{}!./path/to/tpl:

this.query is set
this.query is of type string
?{}

As such, loader-utils.parseQuery will throw that error if neither options nor a query is supplied. See https://github.com/webpack/loader-utils/blob/c937e8c77231b42018be616b784a6b45eac86f8a/lib/parseQuery.js#L11 for the parseQuery() code.

Note that the webpack loaders API documentation omits that this.query is set to an empty string if the query is "undefined". If that didn't happen, at least !!loader?!./path/to/tpl would work correctly.
However, there is a shorthand to checking for an options object or passing the query to loader-utils.parseQuery() documented right below: https://webpack.js.org/api/loaders/#thisgetoptionsschema

Using this getOptions() would replace both Lines 12 and 15 in index.js, I assume.

OffTopic:
To be honest, webpack is already at version 5 (beta) and this loader does some v4 stuff incorrectly in a branch called 3.x... I'm ditching this loader and giving that whole "do everything through webpack" a thorough reconsideration. There's an awful lot of dependencies that could break at any given moment (like this one). It was fun to learn this new-fangled webdev stuff, but I don't think I need that for my personal projects.

Thanks for playing.

@tubbo
Copy link

tubbo commented Jul 6, 2020

I'm also seeing this happen, and it definitely wasn't happening before. Using that weird !!ejs-compiled-loader?{}! prefix syntax fixed it for me, but that's just awful. My loader is pretty basic, and I'm not using this alongside HtmlWebpackPlugin, just a Webpacker app with Rails.

antun added a commit to antun/ejs-compiled-loader that referenced this issue Aug 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants