轻松配置Webpack

在学习react的时候经常遇到别人所说的webpack,出于好奇我花费了半天的时间学习了一下它,不得不说webpack很强大,很适用于实际开发。

webpack和gulp

webpack和gulp相似,可以取代一部分gulp的操作(压缩/合并/编译文件等),gulp的配置文件是gulpfile.js,而webpack的配置文件是webpack.config.js。本人比较喜欢gulp的管道编写方式,但是webpack编写起来也不麻烦,而且支持CommonJS的书写方式。

安装webpack

你需要全局安装webpack和它的服务端webpack-dev-server

npm install webpack -g
npm install webpack-dev-server -g

使用webpack

就像gulp一样,你需要一个配置文件(配置文件不是必须的,webpack允许直接在控制台操作,但是会很麻烦)。下面通过几个例子来说明如何使用webpack

一、ES6转ES5

第一个例子是将es6转化成es5,新建wp-es6-5文件夹

安装插件

npm install babel-core babel-preset-es2015 --save-dev
npm install babel-loader --save-dev //webpack的babel加载器

下面来配置webpack.config.js

module.exports={
    entry:"./main.js", //webpack的入口文件
    output:{
        path:"./bin", //指定入口文件编译后输出的路径
        filename:"app.js" //指定入口文件编译后输出的文件名
    },
    module:{
        loaders:[{ //loaders是一个数组,由若干个对象组成,每个对象就是一个操作
            test:/\.js$/, //对js文件生效
            exclude:/node_modules/, //操作不包括node_modules文件夹
            loader:"babel-loader", //使用babel加载器,为了书写方便也可以把-loader去掉
            query:{
                presets:["es2015"] //执行babel的es2015转换规则
            }
        }]
    }
}

写一下入口文件吧

//main.js
class MyClass{
    constructor(x,y){
        this.x=x;
        this.y=y;
    }
    print(){
        return `(${this.x},${this.y})`;
    }
}
var myclass=new MyClass(2,3);
console.log(myclass.print());

下面打开命令行,进入到当前文件夹下(wp-es6-5),运行webpack

此时你会发现多了一个bin文件夹,里面含有一个app.js,说明webpack已经成功地将main.js转换成了es5并保存在了bin文件夹下面的app.js中。我们可以看一下app.js中的内容

//部分代码
var MyClass = function () {
        function MyClass(x, y) {
            _classCallCheck(this, MyClass);

            this.x = x;
            this.y = y;
        }

        _createClass(MyClass, [{
            key: "print",
            value: function print() {
                return "(" + this.x + "," + this.y + ")";
            }
        }]);

        return MyClass;
    }();

    var myclass = new MyClass(2, 3);
    console.log(myclass.print());

不得不说webpack添加了很多其他的代码,但是es6的确转换成了es5。

我们在根目录下新建一个index.html

<html>
    <body>
        <script src="bin/app.js"></script>
    </body>
</html>

在浏览器端运行index.html,在控制台里可以看到正确地运行结果(2,3)

我们也可以将webpack更加人性化一些,比如显示进度条或者实时监听,只需要运行webpack时加上后续指令

webpack --progress //编译时显示进度条
webpack --colors //增加配色
webpack --watch //实时监听
webpack --progress --colors --watch //整合以上功能

二、CSS模块加载

webpack的模块加载机制不止适用于js,css/image均可以通过require加载。新建wp-css文件夹

安装插件

npm install style-loader --save-dev
npm install css-loader --svae-dev

配置webpack.config.js

module.exports={
    entry:"./main.js",
    output:{
        path:__dirname+"/bin",//__dirname代表当前webpack.config.js所在的路径
        filename:"app.js"
    },
    module:{
        loaders:[{
            test:/\.css$/, 
            exclude:/node_modules/,
            loader:"style!css"//多个加载器通过字符串的形式以!分离
        }]
    }
}

为了体现webpack对CommonJS的支持,我新建了export.js导出模块,入口文件main.js引入它

//exports.js
var obj={name:"SunnyChuan",age:21};
module.exports=obj;
//style.css
body {
  background-color: #68b1ed;
}
//main.js
require("!style!css!./style.css");
var obj=require("./export.js");
doucment.body.innerHTML=obj.name+" "+obj.age;

和例子一相同,我们需要一个index.html文件引入app.js,在浏览器中运行

三、React+ES6

安装react和所需插件,既然目前react流行es6的书写,那就把es6转es5所需插件也安装上

npm install react --save-dev
npm install react-dom --save-dev
npm install babel-core --save-dev
npm install babel-preset-es2015 --save-dev
npm install babel-preset-react //将jsx语法转换成正常js的规则
npm install babel-loader

配置webpack.config.js

module.exports={
    entry:"./main.js",
    output:{
        path:__dirname+"/bin",
        filename:"app.js"
    },
    module:{
        loaders:[{
            test:/\.js$/,
            exclude:/node_modules/,
            loader:"babel",
            query:{
                presets:["es2015","react"] //执行babel的es2015和react转换规则
            }
        }]
    }
}

用react书写入口文件

//main.js
import React from 'react'; //现在可以用es6写react了
import ReactDOM from 'react-dom';
var MyComponent=React.createClass({
    render:function(){
        return (<div>Hello,SunnyChuan</div>);
    }
});
ReactDOM.render(<MyComponent/>,document.getElementById("ss"));

<!--index.html-->
<html>
    <body>
        <div id="ss"></div>
        <script src="bin/app.js"></script>
    </body>
</html>

运行webpack后打开index.html

四、UglifyJs插件

webpack自带了一些插件,通过模块导入后可以直接使用

配置webpack.config.js

var webpack = require("webpack");//UglifyJs是webpack自带的插件,因此无需自己安装
var uglifyJsPlugin = webpack.optimize.UglifyJsPlugin; //获取uglifyJS插件
module.exports = {
    entry: "./main.js",
    output: {
        path: "./bin",
        filename: "app.js"
    },
    plugins: [
        new uglifyJsPlugin({ //plugins是一个数组,每一个成员都是一个插件,只需要require相应插件并添加到该数组中完成相应的配置即可
            compress: {
                warnings: false
            }
        })
    ]
}

我在入口文件中写了一个数组去重函数

var func=function(arr){
    var temp=[];
    for(var i =0;i<arr.length;i++){
        if(temp.indexOf(arr[i])==-1)temp.push(arr[i]);
    }
    return temp;
}
console.log(func([1,1,2,2,3,3]));

运行webpack后打开bin文件夹下的app.js,代码的确压缩了,但也得不可读了

!function(r){function n(e){if(o[e])return o[e].exports;var t=o[e]={exports:{},id:e,loaded:!1};return r[e].call(t.exports,t,t.exports,n),t.loaded=!0,t.exports}var o={};return n.m=r,n.c=o,n.p="",n(0)}([function(r,n){var o=function(r){for(var n=[],o=0;o<r.length;o++)n.indexOf(r[o])==-1&&n.push(r[o]);return n};console.log(o([1,1,2,2,3,3]))}]);

在bin文件夹下使用node运行app.jsnode app,显示的结果是[1,2,3],说明代码压缩成功

HTML插件和OpenBrowser插件

HTML插件用于自动生成index.html,OpenBrowser则是自动打开index.html。与UglifyJs不同的是,这两个插件都不是webpack自带的插件,因此需要npm安装。

npm安装的插件名称需要在官网的list of plugins中找到自己要用到的插件,然后将该插件的驼峰命名法转化为小写并且单词见用“-”链接即可。比如官网中的HtmlWebpackPlugin对应着html-webpack-plugin

npm install html-webpack-plugin --save-dev
npm open-browser-webpack-plugin --save-dev

配置webpack.config.js

var HtmlwebpackPlugin = require('html-webpack-plugin'); //引入相应的插件,注意写法上和webpack自带插件的区别
var OpenBrowserPlugin = require('open-browser-webpack-plugin');
module.exports = {
  entry: './main.js', //在本例中不需要自己的js文件,但是入口文件是必须的,因此需要新建一个入口文件,里面可以什么都不写
  output: {
    path: __dirname,
    filename: 'app.js'
  },
  plugins: [
    new HtmlwebpackPlugin({
      title: 'Webpack-demos',
      filename: 'index.html'
    }),
    new OpenBrowserPlugin({
      url: 'http://localhost:8080'
    })
  ]
};

运行webpack后会发现根目录生成了一个index.html,内容如下

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Webpack-demos</title>
  </head>
  <body>
  <script type="text/javascript" src="app.js"></script></body>
</html>

运行webpack-dev-server开启服务器后会自动打开index.html

将最终打包的js文件和框架(库)分离开

webpack默认是将你的入口文件所引入的库和框架全部打包到最终文件,假设现在存在一个入口文件main.js,里面使用了react+es6的写法,那么最终打包出来的文件可能达到几kb的大小,而其中绝大多数代码都是react的。使用CommonsChunkPlugin可以解决这个问题

var webpack=require("webpack");
module.exports={
    entry:{//定义两个入口文件,一个用于包含业务逻辑,一个用于包含框架(库)
        vendor:["react","react-dom"],
        main:"./main.js",
    },
    output:{
        path:__dirname,
        filename:"app.js",
    },
    module:{
        loaders:[{
            test:/\.js$/,
            exclude:/node_modules/,
            loader:"babel",
            query:{
                presets:["react","es2015","stage-0"]
            }
        }]
    },
    plugins:[
            new webpack.optimize.CommonsChunkPlugin({
                name:"vendor",//匹配上述的入口文件
                filename:"vendor.js"//单独生成vendor.js
            })
    ]
}

你会发现app.js的大小骤减,因为react的代码已经从app.js中抽离到vendor.js里了,接下来只需将app.js和vendor.js这两个文件引入到html中即可(vendor要在app之前)。

<html>
    <head>
        <meta charset="utf-8"/>
    </head>
    <body>
        <div id="ss"></div>
        <script src="vendor.js"></script>
        <script src="app.js"></script>
    </body>
</html>

总结

webpack是一个十分强大的工具,本文只是简单地对一些自动化操作进行了配置,除了本文介绍的jsx/es6的编译外,sass和less的编译也是比较常用的,loader的写法都相似。webpack支持很多插件,可以通过官方文档和阮一峰的webpack教程进行学习。

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

推荐阅读更多精彩内容