-
Notifications
You must be signed in to change notification settings - Fork 599
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
Uglify terser #243
Uglify terser #243
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
**/__mocks__/** | ||
**/__tests__/** | ||
build | ||
src.real | ||
yarn.lock |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow strict-local | ||
* @format | ||
* @emails oncall+js_foundation | ||
*/ | ||
'use strict'; | ||
|
||
import type {BabelSourceMap} from '@babel/core'; | ||
|
||
jest.mock('terser', () => ({ | ||
minify: jest.fn(code => { | ||
return { | ||
code: code.replace(/(^|\W)\s+/g, '$1'), | ||
map: {}, | ||
}; | ||
}), | ||
})); | ||
|
||
const minify = require('..'); | ||
const {objectContaining} = jasmine; | ||
|
||
function getFakeMap(): BabelSourceMap { | ||
return { | ||
version: 3, | ||
sources: ['?'], | ||
mappings: '', | ||
names: [], | ||
}; | ||
} | ||
|
||
describe('Minification:', () => { | ||
const filename = '/arbitrary/file.js'; | ||
const code = 'arbitrary(code)'; | ||
let map: BabelSourceMap; | ||
let terser; | ||
|
||
beforeEach(() => { | ||
terser = require('terser'); | ||
terser.minify.mockClear(); | ||
terser.minify.mockReturnValue({code: '', map: '{}'}); | ||
map = getFakeMap(); | ||
}); | ||
|
||
it('passes file name, code, and source map to `terser`', () => { | ||
minify.withSourceMap(code, map, filename); | ||
expect(terser.minify).toBeCalledWith( | ||
code, | ||
objectContaining({ | ||
sourceMap: { | ||
content: map, | ||
includeSources: false, | ||
}, | ||
}), | ||
); | ||
}); | ||
|
||
it('passes code to `terser` when minifying without source map', () => { | ||
minify.noSourceMap(code); | ||
expect(terser.minify).toBeCalledWith( | ||
code, | ||
objectContaining({ | ||
sourceMap: { | ||
content: undefined, | ||
includeSources: false, | ||
}, | ||
}), | ||
); | ||
}); | ||
|
||
it('returns the code provided by terser', () => { | ||
terser.minify.mockReturnValue({code, map: '{}'}); | ||
const result = minify.withSourceMap('', getFakeMap(), ''); | ||
expect(result.code).toBe(code); | ||
expect(minify.noSourceMap('')).toBe(code); | ||
}); | ||
|
||
it('parses the source map object provided by terser and sets the sources property', () => { | ||
terser.minify.mockReturnValue({map: JSON.stringify(map), code: ''}); | ||
const result = minify.withSourceMap('', getFakeMap(), filename); | ||
expect(result.map).toEqual({...map, sources: [filename]}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{ | ||
"name": "metro-minify-terser", | ||
"version": "0.45.2", | ||
"description": "🚇 Terser-based minifier alternative for Metro", | ||
"main": "src/index.js", | ||
"repository": { | ||
"type": "git", | ||
"url": "git@github.com:facebook/metro.git" | ||
}, | ||
"scripts": { | ||
"prepare-release": "test -d build && rm -rf src.real && mv src src.real && mv build src", | ||
"cleanup-release": "test ! -e build && mv src build && mv src.real src" | ||
}, | ||
"license": "MIT", | ||
"dependencies": { | ||
"metro-minify-uglify": "^0.45.2", | ||
"terser": "^3.8.2" | ||
}, | ||
"devDependencies": {} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow strict-local | ||
* @format | ||
*/ | ||
|
||
'use strict'; | ||
|
||
import type { | ||
MetroMinifier, | ||
MinifyOptions, | ||
ResultWithMap, | ||
ResultWithoutMap, | ||
} from './types'; | ||
import type {BabelSourceMap} from '@babel/core'; | ||
|
||
const minifier = require('metro-minify-uglify/src/minifier'); | ||
const terser = require('terser'); | ||
|
||
export type {MetroMinifier} from './types.js.flow'; | ||
export type {ResultWithMap} from './types.js.flow'; | ||
export type {ResultWithoutMap} from './types.js.flow'; | ||
|
||
function noSourceMap( | ||
code: string, | ||
options?: MinifyOptions = {}, | ||
): ResultWithoutMap { | ||
return minifier.noSourceMap(code, options, terser); | ||
} | ||
|
||
function withSourceMap( | ||
code: string, | ||
sourceMap: ?BabelSourceMap, | ||
filename: string, | ||
options?: MinifyOptions = {}, | ||
): ResultWithMap { | ||
return minifier.withSourceMap(code, sourceMap, filename, options, terser); | ||
} | ||
|
||
const metroMinifier: MetroMinifier = { | ||
noSourceMap, | ||
withSourceMap, | ||
}; | ||
|
||
module.exports = metroMinifier; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
* @flow | ||
* @format | ||
*/ | ||
|
||
'use strict'; | ||
|
||
import type {BabelSourceMap} from '@babel/core'; | ||
import type {MinifyOptions} from 'metro/src/JSTransformer/worker'; | ||
|
||
export type {MinifyOptions}; | ||
|
||
export type ResultWithMap = { | ||
code: string, | ||
map: BabelSourceMap, | ||
options?: MinifyOptions, | ||
}; | ||
|
||
export type ResultWithoutMap = string; | ||
|
||
type MinifierWithSourceMap = ( | ||
code: string, | ||
inputMap?: ?BabelSourceMap, | ||
filename: string, | ||
options?: MinifyOptions, | ||
) => ResultWithMap; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing |
||
|
||
type MinifierWithoutSourceMap = ( | ||
code: string, | ||
options?: MinifyOptions, | ||
) => ResultWithoutMap; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing |
||
|
||
export type MetroMinifier = { | ||
noSourceMap: MinifierWithoutSourceMap, | ||
withSourceMap: MinifierWithSourceMap, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,17 +23,19 @@ import type {BabelSourceMap} from '@babel/core'; | |
function noSourceMap( | ||
code: string, | ||
options?: MinifyOptions = {}, | ||
uglifyModule: ?Object, | ||
): ResultWithoutMap { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Types need updating here to add the extra |
||
return minify(code, undefined, options).code; | ||
return minify(code, undefined, options, uglifyModule).code; | ||
} | ||
|
||
function withSourceMap( | ||
code: string, | ||
sourceMap: ?BabelSourceMap, | ||
filename: string, | ||
options?: MinifyOptions = {}, | ||
uglifyModule: ?Object, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Types need updating here to add the extra |
||
): ResultWithMap { | ||
const result = minify(code, sourceMap, options); | ||
const result = minify(code, sourceMap, options, uglifyModule); | ||
const map: BabelSourceMap = JSON.parse(result.map); | ||
|
||
map.sources = [filename]; | ||
|
@@ -45,8 +47,9 @@ function minify( | |
inputCode: string, | ||
inputMap: ?BabelSourceMap, | ||
options: MinifyOptions, | ||
uglifyModule: ?Object, | ||
) { | ||
const result = uglify.minify(inputCode, { | ||
const result = (uglifyModule || uglify).minify(inputCode, { | ||
mangle: { | ||
toplevel: false, | ||
reserved: options.reserved, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Version needs to be hard set - e.g. remove the "^" - node CI tests should be good after this. 👍