Skip to content

How to turn off Mangle? (keep_fnames: true) #407

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

Closed
1 of 5 tasks
BenGWeeks opened this issue Feb 3, 2017 · 8 comments
Closed
1 of 5 tasks

How to turn off Mangle? (keep_fnames: true) #407

BenGWeeks opened this issue Feb 3, 2017 · 8 comments
Assignees
Labels
area:tooling Category: Development tooling status:tracked Currently tracked with Microsoft’s internal issue tracking system. DO NOT ADD/REMOVE (MSFT managed)

Comments

@BenGWeeks
Copy link

Category

  • Question
  • Typo
  • Bug
  • Enhancement / Suggestion
  • Additional article idea

How to I switch off mangle? I know with the SPFx project we don't have a webpack config, and it's in the gulpfile.json, but how would I go about putting in:

new webpack.optimize.UglifyJsPlugin({
        beautify: false, //prod
        mangle: { screw_ie8 : true, keep_fnames: true }, //prod 
        compress: { screw_ie8: true }, //prod
        comments: false //prod
      }),

Related issue is here:

#406

@nickpape
Copy link

nickpape commented Feb 3, 2017

We haven't provided a simple way to adjust the configuration options of the UglifyJS plugin, however, you can achieve the objective by replacing the Microsoft-provided plugin with your own. Here is an example:

build.configureWebpack.setConfig({
  additionalConfiguration: (config) => {
    var webpack = require('webpack');

    // Remove the Microsoft-provided Uglify plugin
    config.plugins.forEach((plugin) => {
      if (plugin instanceof webpack.optimize.UglifyJsPlugin) {
        var index = config.plugins.indexOf(plugin);
        config.plugins.splice(index, 1);
      }
    });

    // If you only want this to happen during a prod build, add the
    // following if statement:
    // if (build.getConfig().production) { ... }

    // Add our custom config plugin
    config.plugins.push(new webpack.optimize.UglifyJsPlugin({
      beautify: false,
      mangle: { screw_ie8 : true, keep_fnames: true },
      compress: {
        screw_ie8: true /*,
        warnings: false */  // if you don't want to see warnings from uglify
      },
      comments: false
    }));

    return config;
  }
});

Please note that we use the following settings in the Uglify plugin:

{
  compress: {
    dead_code: true,
    warnings: false
  },
  mangle: true
}

If you think it would be helpful, we can also provide an easy way to set the configuration for the Uglify plugin using a JSON config file, however, that would not be in the upcoming GA release.

@BenGWeeks
Copy link
Author

BenGWeeks commented Feb 3, 2017

I think in an ideal world we would be able to import a standard webpack type configuration file (perhaps webpack.dev.json and webpack.production.json). Webpack is not completing at the moment, and I have:

'use strict';

const gulp = require('gulp');
const build = require('@microsoft/sp-build-web');
var spsave = require('gulp-spsave');
var auth = require('./_private/settings');

// Ref: https://github.com/webpack/docs/wiki/configuration#outputpublicpath

build.configureWebpack.setConfig({
  additionalConfiguration: (config) => {
    var webpack = require('webpack');

    // Angular 2 fix, see: https://github.com/angular/angular/issues/10618
    // Remove the Microsoft-provided Uglify plugin
    // If you only want this to happen during a prod build, add the
    // following if statement:
    // if (build.getConfig().production) { ... }
    config.plugins.forEach((plugin) => {
      if (plugin instanceof webpack.optimize.UglifyJsPlugin) {
        var index = config.plugins.indexOf(plugin);
        config.plugins.splice(index, 1);
      }
    });
    // Add our custom config plugin
    config.plugins.push(new webpack.optimize.UglifyJsPlugin({
      beautify: false,
      mangle: { screw_ie8 : true, keep_fnames: true },
      compress: {
        screw_ie8: true /*,
        warnings: false */  // if you don't want to see warnings from uglify
      },
      comments: false
    }));

    //config.devtool = 'source-map';

    // Workaround for ng2, see: https://github.com/angular/material2/issues/1335#issuecomment-277157354
    //config.htmlLoader = {
    //    minimize: false // workaround for ng2
    //}

    config.module.loaders.push([
      { test: /\.(woff|woff2)$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
      { test: /\.ttf$/, loader: "file-loader" },
      { test: /\.html$/, loader: "html-loader?-minimize" }, // workaround for ng2
      // { test: /\.html$/, loader: "html?-minimize" }, // workaround for ng2
      // { test: /\.html$/, loader: "html-loader", query: { minimize: false } }, // workaround for ng2
      { test: /\.eot$/, loader: "file-loader" },
      { test: /\.svg$/, loader: "file-loader" },
      { test: /\.scss$/, loaders: ["style-loader", "css-loader?sourceMap", "sass-loader?sourceMap"]}      
    ]);

    return config;
  }
});

build.initialize(gulp);

gulp.task('changeBase', function(){
 // gulp.src(['./dist/index.aspx'])
 //   .pipe(replace('<base href="/">', '<base href="/sites/Development/R2Dev/SitePages/ng2/index.aspx">'))
 //   .pipe(gulp.dest('./dist'));
});

gulp.task("spsave",['changeBase'], function () {
    return gulp.src(["./dist/**/*.*"])
        .pipe(spsave({
            siteUrl: auth.siteCollectionUrl,
            folder: "SiteAssets/[somefolder]",
            flatten: false
        }, auth));
});

Related issue:

angular/components#1335 (comment)

@BenGWeeks
Copy link
Author

I would also add, that personally I would prefer if we switch off as much of this bundling stuff as possible, in the sense that for dev, we already have 1 level of abstraction with code being transposed from .ts to .js, but when the code is also bundled up into inline css and a single js file makes it again more difficult to debug. That's the kind of thing we can switch on if we want to be clever - and probably at SP1 ;-)

@BenGWeeks
Copy link
Author

Ah, OK, does eventually fail with:

Declarations in unreachable code! [requirements-form.bundle.js:190,12635]
Dropping unreachable code [requirements-form.bundle.js:190,21900]
Declarations in unreachable code! [requirements-form.bundle.js:190,21900]

Error - [webpack] 'dist':
./lib/webparts/requirementsForm/app/app.component.html
Module build failed: Error: Parse Error: <h1 style=\"display:none\">{{title}}</h
1>\n\n<div class=\"container gt-container-fluid gt-container-form\">\n    <div c...

@BenGWeeks
Copy link
Author

OK, looks like this works:

'use strict';

const gulp = require('gulp');
const build = require('@microsoft/sp-build-web');
var spsave = require('gulp-spsave');
var auth = require('./_private/settings');

// Ref: https://github.com/webpack/docs/wiki/configuration#outputpublicpath

build.configureWebpack.setConfig({
  additionalConfiguration: (config) => {
    var webpack = require('webpack');

    // Angular 2 fix, see: https://github.com/angular/angular/issues/10618
    // Remove the Microsoft-provided Uglify plugin
    // If you only want this to happen during a prod build, add the
    // following if statement:
    // if (build.getConfig().production) { ... }
    config.plugins.forEach((plugin) => {
      if (plugin instanceof webpack.optimize.UglifyJsPlugin) {
        var index = config.plugins.indexOf(plugin);
        config.plugins.splice(index, 1);
      }
    });
    // Add our custom config plugin
    config.plugins.push(new webpack.optimize.UglifyJsPlugin({
      beautify: false,
      mangle: false,
    }));

    //config.devtool = 'source-map';

    // Workaround for ng2, see: https://github.com/angular/material2/issues/1335#issuecomment-277157354
    config.htmlLoader = {
        minimize: false // workaround for ng2
    }

    config.module.loaders.push([
      { test: /\.(woff|woff2)$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
      { test: /\.ttf$/, loader: "file-loader" },
      //{ test: /\.html$/, loader: "html-loader?-minimize" }, // workaround for ng2
      { test: /\.html$/, loader: "html?interpolate=require&-minimize" }, // workaround for ng2
      // { test: /\.html$/, loader: "html-loader", query: { minimize: false } }, // workaround for ng2
      { test: /\.eot$/, loader: "file-loader" },
      { test: /\.svg$/, loader: "file-loader" },
      { test: /\.scss$/, loaders: ["style-loader", "css-loader?sourceMap", "sass-loader?sourceMap"]}      
    ]);

    return config;
  }
});

build.initialize(gulp);

gulp.task('changeBase', function(){
 // gulp.src(['./dist/index.aspx'])
 //   .pipe(replace('<base href="/">', '<base href="/sites/Development/R2Dev/SitePages/ng2/index.aspx">'))
 //   .pipe(gulp.dest('./dist'));
});

gulp.task("spsave",['changeBase'], function () {
    return gulp.src(["./dist/**/*.*"])
        .pipe(spsave({
            siteUrl: auth.siteCollectionUrl,
            folder: "SiteAssets/GrantThornton",
            flatten: false
        }, auth));
});

And it's now giving a template error, but that would seem to be a separate issue:

Unhandled Promise rejection: Template parse errors:
Unexpected closing tag "legend" (">\n            <fieldset class=\"gt-fieldset\">\n                <legend class=\"gt-legend\">Details[ERROR ->]</legend>\n                <div class=\"row gt-row\">\n                    <div class=\"col-6\"><labe"): t@0:238
Unexpected closing tag "label" ("s=\"row gt-row\">\n                    <div class=\"col-6\"><label for=\"title\">Requirements Title:[ERROR ->]</label>

Where the template is (which looks fine to me?):

<div class="container gt-container-fluid gt-container-form">
    <div class="row">
        <div class="col-sm-6">
            <fieldset class="gt-fieldset">
                <legend class="gt-legend">Details</legend>
                <div class="row gt-row">
                    <div class="col-6"><label for="title">Requirements Title:</label></div>
                    <div class="col-6"><input id="title" type="text" class="k-textbox" [(ngModel)]="Requirement.Title"/></div>
                </div>
                <div class="row gt-row">
                    <div class="col-12"><label for="details">Requirements Details:</label></div>
                </div>
                <div class="row gt-row">
                    <div class="col-12">
                        <textarea id="details" class="k-textbox gt-textbox" [(ngModel)]="Requirement.Details"></textarea>
                    </div>
                </div>
                <div class="row gt-row">
                    <div class="col-6"><label for="rating">Requirement Rating:</label></div>
                    <div class="col-6"><kendo-dropdownlist id="ratings" [data]="ratingsData" [textField]="'ProductName'" [valueField]="'ProductID'" [defaultItem]="ratingsPlaceHolder"></kendo-dropdownlist></div>
                </div>
                <div class="row gt-row">
                    <div class="col-6"><label for="status">Approval Status:</label></div>
                    <div class="col-6"><kendo-dropdownlist id="approvalStatus" [data]=""></kendo-dropdownlist></div>
                </div>
            </fieldset>
            <fieldset class="gt-fieldset">
                <legend class="gt-legend">Attachments</legend>
                <div class="row gt-row">
                    <div class="col-12"><label for="attachments">Drag and drop files of click "Select" to browse:</label></div>
                </div>
                <div class="row gt-row">
                    <div class="col-12">
                        <kendo-upload
                            id="Attachments"
                            [saveUrl]=""
                            [removeUrl]=""
                            [disabled]="">
                        </kendo-upload>
                    </div>
                </div>
            </fieldset>
        </div>
        <div class="col-sm-6">
            <kendo-tabstrip>
                <kendo-tabstrip-tab [title]="'Framework Items'" [selected]="true">
                    <template kendoTabContent>
                        <div class="row gt-row">
                            <div class="col-6"><label for="framework">Framework Items:</label></div>
                            <div class="col-6"><kendo-multiselect [data]="frameworkItems" [value]="" [placeholder]="'Framework Items'"></kendo-multiselect></div>
                        </div>
                        <div class="row gt-row">
                            <div class="col-12 gt-col-addremovebuttons">
                                <button kendoButton (click)="onButtonClick()" [primary]="true">+</button>
                                <button kendoButton (click)="onButtonClick()" [primary]="true">-</button>
                            </div>
                        </div>
                        <div class="row gt-row">
                            <div class="col-12">
                                <kendo-grid [data]="frameworkItemsData" [height]="200">
                                    <kendo-grid-column field="FrameworkLocation" title="ID">
                                    </kendo-grid-column>
                                    <kendo-grid-column field="FrameworkTitle" title="Name">
                                    </kendo-grid-column>
                                </kendo-grid>
                            </div>
                        </div>
                    </template>
                </kendo-tabstrip-tab>
                <kendo-tabstrip-tab [title]="'Related Actions'">
                    <template kendoTabContent>
                        <div class="row gt-row">
                            <div class="col-6"><label for="actions">Related Actions:</label></div>
                            <div class="col-6"><kendo-multiselect [data]="actionItems" [value]="" [placeholder]="'Actions'"></kendo-multiselect></div>
                        </div>
                    </template>
                </kendo-tabstrip-tab>
             </kendo-tabstrip>
        </div>
    </div>
    <div class="row gt-row">
        <div class="col-12 gt-col-buttons">
            <button kendoButton (click)="saveChanges()" [primary]="true">Save</button>
            <button kendoButton (click)="onButtonClick()" [primary]="false">Edit</button>
            <button kendoButton (click)="deleteRecord()" [primary]="false">Delete</button>
            <button kendoButton (click)="onButtonClick()" [primary]="false">Close</button>
        </div>
    </div>
</div>

Thanks for the help :-)

@chakkaradeep chakkaradeep added the area:tooling Category: Development tooling label Feb 8, 2017
@amishra0909 amishra0909 added the status:tracked Currently tracked with Microsoft’s internal issue tracking system. DO NOT ADD/REMOVE (MSFT managed) label May 9, 2017
@iclanton
Copy link
Contributor

Sounds like you got this working. We'll work on making the build tools more easily configurable in future releases.

@swissgamedev
Copy link

Did you get a chance to work more on this? Are there now other options to disable uglify/minimize so one can debug the solution properly?

@msft-github-bot
Copy link
Collaborator

Issues that have been closed & had no follow-up activity for at least 7 days are automatically locked. Please refer to our wiki for more details, including how to remediate this action if you feel this was done prematurely or in error: Issue List: Our approach to locked issues

@SharePoint SharePoint locked as resolved and limited conversation to collaborators Jan 29, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area:tooling Category: Development tooling status:tracked Currently tracked with Microsoft’s internal issue tracking system. DO NOT ADD/REMOVE (MSFT managed)
Projects
None yet
Development

No branches or pull requests

7 participants