简体   繁体   中英

How to remove \n and \t from webpack compiled template literal?

I am developing a javascript plugin, which uses es6 template literals to generate a template, I am attaching a piece of code in my plugin.

"use strict";
(function () {
window.project = {
    template: {
        generateHtmlTemplate: function(data) {
        var template = `
             <div class="main">
                <div class="wrap">
                    <input type="text" value="${data.val}" />
                </div>
             </div>`;
       return template;
      }
   }
}

When i tried to get build via webpack babel transpiles it to es5 so the template literals like the following. This is the webpack minified babel transpiled version of the plugin. This minified transpiled file is used by users. This production build minified file contains \\n \\t, this is what i want to remove.

(Just think like jQuery development version written with es6 and using babel and webpack to transpile and minify it to form jquery.min.js)

"use strict";
(function () {
window.project = {
    template: {
        generateHtmlTemplate: function(data) {
        var template = '<div class="main">\n\t\t\t<div class="wrap">\n\t\t\t\t<input type="text" value="${data.val}" />\n\t\t\t\t\t</div>\n\t\t\t\t\t</div>';
       return template;
      }
   }
}

It is filled with \\n and \\t. I have tried some the solutions in stackoverflow . But it doesn't work for me. What this common-tags package does is it injects the code to remove \\n and \\t along with the plugin code .

What I want

Just remove \\n and \\t from the output file.

What I tried

  1. I have tried webpack string replace plugin to replace \\t and \\n. But it doesn't worked. It take source code and tried to replace before transpiler works.
  2. I got a hack to solve new line problem by adding \\ to the end of each line (also code becomes messy). But even though \\t is there.
  3. If i try to regEx all \\n and \\t after build and replacing it is not a good method, it is error prone.

Webpack production build config

const TerserPlugin = require('terser-webpack-plugin');
const ReplacePlugin = require('webpack-plugin-replace');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const MiniCssExtactPlugin = require('mini-css-extract-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const BrotliPlugin = require('brotli-webpack-plugin');

const config = {
    mode: 'production',
    entry: ['./src/source.js', './src/ufe.css'],
    output: {
        path: __dirname + '/dist/',
        filename: 'source.min.js'
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                use: ['babel-loader']
            },
            {
                test: /\.css$/,
                use: [MiniCssExtactPlugin.loader, 'css-loader']
            },
            {
                test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
                use: 'url-loader?limit=100000'
            }
        ]
    },

    plugins: [
        // new uglifyJsPlugin(),
        // new ReplacePlugin({
        //     values: {
        //         "\n": '',
        //         "\t": ''
        //     }
        // })
        }),
        // Brotli compression output for files
        new CompressionPlugin({
            filename: '[path].gz[query]',
            algorithm: 'gzip',
            test: /\.js$|\.css$|\.html$|\.svg$/,
            threshold: 1024,
            minRatio: 0.8
        }),
        new BrotliPlugin({
            asset: '[path].br[query]',
            test: /\.js$|\.css$|\.html$|\.svg$/,
            threshold: 1024,
            minRatio: 0.8
        })
        // new HTMLWebpackPlugin({
        //  template: path.resolve(__dirname, 'index.html')
        // }),
        // new webpack.HotModuleReplacementPlugin()
    ],
    optimization: {
        minimizer: [
            new TerserPlugin({
                terserOptions: {
                    ecma: undefined,
                    warnings: false,
                    parse: {},
                    compress: {},
                    mangle: true, // Note `mangle.properties` is `false` by default.
                    module: false,
                    output: null,
                    toplevel: false,
                    nameCache: null,
                    ie8: false,
                    keep_classnames: undefined,
                    keep_fnames: false,
                    safari10: false,
                }
            }),
            new OptimizeCssAssetsPlugin({})
        ],
    },
    resolve: {
        extensions: ['.js', '.svg']
    },
    devServer: {
        port: 3000,
        contentBase: __dirname + '/build',
        inline: false
    }
};
module.exports = config;

Any suggestions to solve this will be much appreciated.

Thanks in advance.

I have got solution for what I want exactly.

Create a babel plugin to remove it.

var pattern = new RegExp("[\n\t ]+", "g");

function transfrom (quasis) {
  ["raw", "cooked"].forEach(function (type) {
    quasis.forEach(function (element) {
      element.value[type] = element.value[type].replace(pattern, " ");
    });
  });  
}

module.exports = function (babel) {
  var t = babel.types;

  return {
    visitor: {
      TaggedTemplateExpression: function (path) {
        let node = path.node;

        if (t.isIdentifier(node.tag, { name: "nowhitespace" })) {
          transfrom(node.quasi.quasis);
          return path.replaceWith(node.quasi);
        }
      }
    }
  };
};

It's bit old, but still works.

https://github.com/WebEngage/babel-plugin-template-string-transform https://engineering.webengage.com/2016/07/15/babel/

That's not how template literals work: they preserve whitespace. This feature is very much on purpose as it allows you to preserve formatting much like formatted strings in other languages (eg heredocs in PHP and triple-quoted strings in python ). If you don't want that behavior, then you can just concatenate plain strings as we did in ye old days prior to ES 6:

window.project = {
    template: {
        generateHtmlTemplate: function(data) {
        var template = '' +
             '<div class="main">' +
                '<div class="wrap">' +
                    '<input type="text" value="' + data.val + '" />' +
                '</div>' +
             '</div>';
        return template;
      }
   }
}

Note that this is harder to read in the source. Whether or not it's worth it to save a handful of bytes in your payload is subjective but FWIW I'd stick with the template string.

Edit

If you really want to use a template but strip the whitespace just do this instead:

function(data) {
    var template = `
        <div class="main">
            <div class="wrap">
                <input type="text" value="${data.val}" />
            </div>
        </div>`.replace(/[\t\n]+/g, ''); // remove all tabs and returns
    return template;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM