03_预编译和混淆

前面两篇文章的例子中采用的开发方式被称作standalone,意思是说把所有需要用到的js文件定义好并放在<script>标签中,然后在另起一个<script>标签用于撰写实际业务场景需要的自定义代码;这种方式的好处是代码的引入、撰写和阅读都非常清晰明了,缺点是所有源码都暴露在html中。

通过利用gulp和其丰富插件库可以完成对多个js文件进行预编译(指定一个文件,工具可以将它所有的依赖组织起来)和压缩,最终产生一个具有混淆性的单js文件;详细的gulp文档说明请移步到这里。

简单的合并

# 创建项目目录结构
[root@localhost ~]# mkdir -p simple_merge/src
[root@localhost ~]# cd simple_merge

# 安装gulp打包组件和react相关的js组件
[root@localhost simple_merge]# cnpm install react react-dom gulp gulp-concat --save-dev

# 将react.js和react-dom.js文件复制到src目录中.
[root@localhost simple_merge]# cp node_modules/react/dist/react.js node_modules/react-dom/dist/react-dom.js src/

# 创建gulpfile.js任务管理文件.
[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

# 查看产出的目录(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

小结: 通过上面gulpfile.js任务管理文件中的代码,是将两个js文件进行简单的合并,可以看得出来原来两个文件的大小分别是606k和125k,合并成单文件bundle.js后,文件的大小是731K正好是两个文件大小的总和。

压缩和混淆

# 创建项目目录结构
[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文件复制到src目录中.
[root@localhost simple_uglify]# cp node_modules/react/dist/react.js node_modules/react-dom/dist/react-dom.js src/

# 创建gulpfile.js任务管理文件.
[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文件复制到src目录中.
[root@localhost simple_uglify]# cp node_modules/react/dist/react.js node_modules/react-dom/dist/react-dom.js src/

# 创建gulpfile.js任务管理文件.
[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

小结: 仅仅是将两个源码文件进行合并其实并没有什么意义,这里将采用uglify插件对合并后的文件进行压缩和混淆。

解决依赖问题

上面两个例子都是针对源码库文件进行合并、压缩和混淆,实际上意义也不大,因为这两个代码跟项目业务代码并没有直接作用。所以这里将会单独列出一个业务代码的js文件,并通过gulp的相关插件来完成依赖问题解决。

# 创建项目目录结构
[root@localhost ~]# mkdir -p spa_jsx/src
[root@localhost ~]# cd spa_jsx/

# 安装相关插件
[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

# 创建.babelrc文件(声明支持es2015和react)
[root@localhost spa_jsx]# vim .babelrc 
{ presets: ["es2015", "react"] }

# 创建源码组件(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;


# 创建源码模版(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')
);


# 创建gulpfile.js任务配置管理文件.
[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会根据
    // import和from关键字去提取相关的依赖库。
    return browserify('src/index.js')   
           .transform(babelify)
           .bundle()
           .pipe(source('bundle.js'))
           .pipe(streamify(uglify()))
           .pipe(gulp.dest('dist/'))
})


# 编译文件(指的是根据index.js去寻找相关的依赖代码,然后整合、压缩和混淆)。
[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环境变量,像.bashrc一样。如果不声明.babelrc的话,那么执行gulpfile.js时就会报错。 若不想声明.babelrc文件,但又要编译es2015的代码,那么可以在将gulpfile.js文件中的.transform(babelify)改为.transform(babelify, {presets: ["es2015", "react"]})即可。
小结: 这个例子是提供单个index.js文件,browserify会根据import和from关键字去提取相关的依赖库。

使用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

# 创建.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"
  }
}

# 执行指令(清除目录)
[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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容