03_預(yù)編譯和混淆

前面兩篇文章的例子中采用的開發(fā)方式被稱作standalone,意思是說把所有需要用到的js文件定義好并放在<script>標(biāo)簽中,然后在另起一個<script>標(biāo)簽用于撰寫實際業(yè)務(wù)場景需要的自定義代碼;這種方式的好處是代碼的引入、撰寫和閱讀都非常清晰明了,缺點是所有源碼都暴露在html中。

通過利用gulp和其豐富插件庫可以完成對多個js文件進(jìn)行預(yù)編譯(指定一個文件,工具可以將它所有的依賴組織起來)和壓縮,最終產(chǎn)生一個具有混淆性的單js文件;詳細(xì)的gulp文檔說明請移步到這里。

簡單的合并

# 創(chuàng)建項目目錄結(jié)構(gòu)
[root@localhost ~]# mkdir -p simple_merge/src
[root@localhost ~]# cd simple_merge

# 安裝gulp打包組件和react相關(guān)的js組件
[root@localhost simple_merge]# cnpm install react react-dom gulp gulp-concat --save-dev

# 將react.js和react-dom.js文件復(fù)制到src目錄中.
[root@localhost simple_merge]# cp node_modules/react/dist/react.js node_modules/react-dom/dist/react-dom.js src/

# 創(chuàng)建gulpfile.js任務(wù)管理文件.
[root@localhost simple_merge]# vim gulpfile.js
var gulp   = require('gulp'),
    concat = require('gulp-concat')

gulp.task('compress', function() {
    return gulp.src('src/*js')
           .pipe(concat('bundle.js'))
           .pipe(gulp.dest('dist/'))
})

# 合并文件
[root@localhost simple_merge]# ./node_modules/gulp/bin/gulp.js compress
[21:30:29] Using gulpfile ~/simple_merge/gulpfile.js
[21:30:29] Starting 'compress'...
[21:30:29] Finished 'compress' after 53 ms

# 查看產(chǎn)出的目錄(dist)
[root@localhost simple_merge]# ls
dist  gulpfile.js  node_modules  src

# 查看合并前的文件
[root@localhost simple_merge]# ls -alh src/
total 736K
drwxr-xr-x 2 root root   42 Mar 20 21:25 .
drwxr-xr-x 5 root root   68 Mar 20 21:30 ..
-rw-r--r-- 1 root root 606K Mar 20 21:25 react-dom.js
-rw-r--r-- 1 root root 125K Mar 20 21:25 react.js

# 查看合并后的文件
[root@localhost simple_merge]# ls -alh dist/
total 732K
drwxr-xr-x 2 root root   23 Mar 20 21:30 .
drwxr-xr-x 5 root root   68 Mar 20 21:30 ..
-rw-r--r-- 1 root root 731K Mar 20 21:30 bundle.js

小結(jié): 通過上面gulpfile.js任務(wù)管理文件中的代碼,是將兩個js文件進(jìn)行簡單的合并,可以看得出來原來兩個文件的大小分別是606k和125k,合并成單文件bundle.js后,文件的大小是731K正好是兩個文件大小的總和。

壓縮和混淆

# 創(chuàng)建項目目錄結(jié)構(gòu)
[root@localhost ~]# mkdir -p simple_uglify/src
[root@localhost ~]# cd simple_uglify/

# 安裝gulp和gulp-uglify
[root@localhost simple_uglify]# cnpm install react react-dom gulp gulp-uglify --save-dev

# 將react.js和react-dom.js文件復(fù)制到src目錄中.
[root@localhost simple_uglify]# cp node_modules/react/dist/react.js node_modules/react-dom/dist/react-dom.js src/

# 創(chuàng)建gulpfile.js任務(wù)管理文件.
[root@localhost simple_uglify]# vim gulpfile.js
var gulp   = require('gulp'),
    concat = require('gulp-concat'),
    uglify = require('gulp-uglify')

gulp.task('compress', function() {
    return gulp.src('src/*js')
           .pipe(concat('bundle.js'))
           .pipe(uglify())
           .pipe(gulp.dest('dist/'))
})

# 將react.js和react-dom.js文件復(fù)制到src目錄中.
[root@localhost simple_uglify]# cp node_modules/react/dist/react.js node_modules/react-dom/dist/react-dom.js src/

# 創(chuàng)建gulpfile.js任務(wù)管理文件.
[root@localhost simple_uglify]# vim gulpfile.js
var gulp   = require('gulp'),
    uglify = require('gulp-uglify')

gulp.task('compress', function() {
    return gulp.src('src/*js')
           .pipe(uglify())
           .pipe(gulp.dest('dist/'))
})

# 合并文件
[root@localhost simple_uglify]# ./node_modules/gulp/bin/gulp.js compress
[21:56:35] Using gulpfile ~/simple_uglify/gulpfile.js
[21:56:35] Starting 'compress'...
[21:56:39] Finished 'compress' after 3.24 s

# 查看合并前的文件
[root@localhost simple_uglify]# ls -alh src/
total 736K
drwxr-xr-x 2 root root   42 Mar 20 21:54 .
drwxr-xr-x 5 root root   88 Mar 20 21:59 ..
-rw-r--r-- 1 root root 606K Mar 20 21:53 react-dom.js
-rw-r--r-- 1 root root 125K Mar 20 21:53 react.js

# 查看合并后的文件
[root@localhost simple_uglify]# ls -alh dist/
total 216K
drwxr-xr-x 2 root root   23 Mar 20 21:59 .
drwxr-xr-x 5 root root   88 Mar 20 21:59 ..
-rw-r--r-- 1 root root 216K Mar 20 21:59 bundle.js

小結(jié): 僅僅是將兩個源碼文件進(jìn)行合并其實并沒有什么意義,這里將采用uglify插件對合并后的文件進(jìn)行壓縮和混淆。

解決依賴問題

上面兩個例子都是針對源碼庫文件進(jìn)行合并、壓縮和混淆,實際上意義也不大,因為這兩個代碼跟項目業(yè)務(wù)代碼并沒有直接作用。所以這里將會單獨列出一個業(yè)務(wù)代碼的js文件,并通過gulp的相關(guān)插件來完成依賴問題解決。

# 創(chuàng)建項目目錄結(jié)構(gòu)
[root@localhost ~]# mkdir -p spa_jsx/src
[root@localhost ~]# cd spa_jsx/

# 安裝相關(guān)插件
[root@localhost spa_jsx]# cnpm install babel babel-core babel-preset-es2015 babel-preset-react babelify gulp gulp-uglify gulp-streamify gulp-uglify browserify vinyl-source-stream react react-dom react-remarkable --save-dev

# 創(chuàng)建.babelrc文件(聲明支持es2015和react)
[root@localhost spa_jsx]# vim .babelrc 
{ presets: ["es2015", "react"] }

# 創(chuàng)建源碼組件(Component)文件
[root@localhost spa_jsx]# vim src/markdown_editor.js
import React, {Component} from 'react';
import Remarkable from 'remarkable';

class MarkdownEditor extends Component {

    constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this);
        this.state = {value: 'Type some *markdown* here!'};
    }

    handleChange(e) {
        this.setState({value: e.target.value});
    }

    getRawMarkup() {
        var md = new Remarkable();
        return { __html: md.render(this.state.value) };
    }

    render() {
        return (
            <div className="MarkdownEditor">
            <h3>Input</h3>
            <textarea onChange={this.handleChange}
                       defaultValue={this.state.value} />
            <h3>Output</h3>
            <div className="content"
                 dangerouslySetInnerHTML={this.getRawMarkup()} />
            </div>
        );
    }
}

export default MarkdownEditor;


# 創(chuàng)建源碼模版(JSX)文件
[root@localhost spa_jsx]# vim src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './markdown_editor';

ReactDOM.render(
    <App />,
    document.getElementById('root')
);


# 創(chuàng)建gulpfile.js任務(wù)配置管理文件.
[root@localhost spa_jsx]# vim gulpfile.js 
var gulp       = require('gulp'),
    uglify     = require('gulp-uglify'),
    browserify = require('browserify'),
    babelify   = require('babelify'),
    source     = require('vinyl-source-stream'),
    streamify  = require('gulp-streamify')

gulp.task('compress', function() {
    process.env.NODE_ENV = 'production';
    // 這里僅制定單個index.js文件, browserify會根據(jù)
    // import和from關(guān)鍵字去提取相關(guān)的依賴庫。
    return browserify('src/index.js')   
           .transform(babelify)
           .bundle()
           .pipe(source('bundle.js'))
           .pipe(streamify(uglify()))
           .pipe(gulp.dest('dist/'))
})


# 編譯文件(指的是根據(jù)index.js去尋找相關(guān)的依賴代碼,然后整合、壓縮和混淆)。
[root@localhost spa_jsx]# ./node_modules/gulp/bin/gulp.js compress

# 查看編譯前的源文件
[root@localhost spa_jsx]# ls -alh src/
total 8.0K
drwxr-xr-x 2 root root  48 Mar 21 00:18 .
drwxr-xr-x 5 root root 104 Mar 21 01:19 ..
-rw-r--r-- 1 root root 169 Mar 21 00:07 index.js
-rw-r--r-- 1 root root 902 Mar 21 00:06 markdown_editor.js


# 查看合并后的文件
[root@localhost spa_jsx]# ls -alh dist/
total 336K
drwxr-xr-x 2 root root   23 Mar 21 01:19 .
drwxr-xr-x 5 root root  104 Mar 21 01:19 ..
-rw-r--r-- 1 root root 334K Mar 21 01:19 bundle.js

提示: .babalrc文件用來聲明babel環(huán)境變量,像.bashrc一樣。如果不聲明.babelrc的話,那么執(zhí)行g(shù)ulpfile.js時就會報錯。 若不想聲明.babelrc文件,但又要編譯es2015的代碼,那么可以在將gulpfile.js文件中的.transform(babelify)改為.transform(babelify, {presets: ["es2015", "react"]})即可。
小結(jié): 這個例子是提供單個index.js文件,browserify會根據(jù)import和from關(guān)鍵字去提取相關(guān)的依賴庫。

使用browserify壓縮混淆(不采用gulp)

不使用.babelrc

# 安裝 uglifyify
[root@localhost spa_jsx]# cnpm install uglifyify --save-dev

# 清除原來的文件
[root@localhost spa_jsx]# rm dist/* -rf

# 壓縮混淆
# 這里要特別注意:命令中的[]兩邊一定要有空格,否則會報模塊找不到。
[root@localhost spa_jsx]# NODE_ENV=productioin browserify -t [ babelify --presets [ react es2015 ] ] src/index.js | ./node_modules/uglify-js/bin/uglifyjs -c > dist/bundle.js

# 查看壓縮混淆后的文件
[root@localhost spa_jsx]# ls -alh dist/
total 472K
drwxr-xr-x 2 root root   20 Mar 23 02:16 .
drwxr-xr-x 5 root root  106 Mar 22 21:47 ..
-rw-r--r-- 1 root root 471K Mar 23 02:17 bundle.js

使用.babelrc

# 清除原來的文件
[root@localhost spa_jsx]# rm dist/* -rf

# 創(chuàng)建.babelrc文件
[root@localhost spa_jsx]# vim .babelrc 
{ presets: [ "react", "es2015" ] }

# 壓縮混淆
[root@localhost spa_jsx]# NODE_ENV=productioin browserify -t [ babelify ] src/index.js | ./node_modules/uglify-js/bin/uglifyjs -c > dist/bundle.js 

# 查看壓縮混淆后的文件
[root@localhost spa_jsx]# ls dist/ -alh
total 472K
drwxr-xr-x 2 root root   20 Mar 23 02:16 .
drwxr-xr-x 5 root root  122 Mar 23 02:19 ..
-rw-r--r-- 1 root root 471K Mar 23 02:20 bundle.js

使用npm + browserify

# 在package.json中加入npm腳本指令
[root@localhost spa_jsx]# cat package.json 
{
  "devDependencies": {
    "babel": "^6.23.0",
    "babel-core": "^6.24.0",
    "babel-preset-es2015": "^6.24.0",
    "babel-preset-react": "^6.23.0",
    "babelify": "^7.3.0",
    "browserify": "^14.1.0",
    "gulp": "^3.9.1",
    "gulp-babel": "^6.1.2",
    "gulp-sourcemaps": "^2.4.1",
    "gulp-streamify": "^1.0.2",
    "gulp-uglify": "^2.1.2",
    "react": "^15.4.2",
    "react-dom": "^15.4.2",
    "react-remarkable": "^1.1.1",
    "reactify": "^1.1.1",
    "uglifyify": "^3.0.4",
    "vinyl-source-stream": "^1.1.0"
  },
  "scripts": {
      "clean": "rm -rf dist/*"
      "build": "NODE_ENV=productioin browserify -t [ babelify ] src/index.js | ./node_modules/uglify-js/bin/uglifyjs -c > dist/bundle.js"
  }
}

# 執(zhí)行指令(清除目錄)
[root@localhost spa_jsx]# npm run clean
> @ clean /root/spa_jsx
> rm -rf dist/*

# 壓縮混淆
[root@localhost spa_jsx]# npm run build

# 查看壓縮混淆后的文件
[root@localhost spa_jsx]# ls -alh dist/
total 472K
drwxr-xr-x 2 root root   23 Mar 23 02:44 .
drwxr-xr-x 5 root root  122 Mar 23 02:43 ..
-rw-r--r-- 1 root root 471K Mar 23 02:44 bundle.js

使用webpack

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容