Search code examples
javascriptwebpackbabeljstemplate-literals

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.


Solution

  • 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/