WebPack1.x 经常使用功用引见

注重:本文形貌的设置只实用webpack1.x;由于webpack已推出2.x并有大批变动,特此说明

概述

Webpack是一款用户打包前端模块的东西。主假如用来打包在浏览器端运用的javascript的。同时也能转换、绑缚、打包其他的静态资本,包括css、image、font file、template等。这里就只管细致的来引见下一些基础功用的运用。

装置

npm install webpack -g

运转webpack

webpack须要编写一个config文件,然后依据这个文件来实行须要的打包功用。我们如今来编写一个最简朴的config。新建一个文件,命名为webpack-config.js。config文件实际上就是一个Commonjs的模块。内容以下:

var path = require('path');
var buildPath = path.resolve(__dirname,"build");
var nodemodulesPath = path.resolve(__dirname,'node_modules');

var config = {
    //进口文件设置
    entry:path.resolve(__dirname,'src/main.js'),
    resolve:{
        extentions:["","js"]//当requrie的模块找不到时,增加这些后缀
    },
    //文件导出的设置
    output:{
        path:buildPath,
        filename:"app.js"
    }
}

module.exports = config;

我的目次构造是如许的:


webpack
    |---index.html
    |---webpack-config.js
    |---src
         |---main.js
         |---js
              |---a.js

main.js文件内容以下:


var a = require('./js/a');
a();
console.log('hello world');
document.getElementById("container").innerHTML = "<p>hello world</p>";

a.js文件内容以下:

module.exports = function(){
    console.log('it is a ');
}

然后我们实行以下的敕令:


webpack --config webpack-config.js --colors

如许我们就能在目次内里看到一个新天生的目次build,目次构造以下:


webpack
    |---index.html
    |---webpack-config.js
    |---build
         |---app.js

然后援用app.js就Ok啦。main.js和模块a.js的内容就都打包到app.js中了。这就演示了一个最简朴的把模块的js打包到一个文件的历程了。

引见webpack config文件

webpack是依据config内里形貌的内容对一个项目举行打包的。接着我们来诠释下config文件中的节点离别代表什么意思。一个config文件,基础都是由以下几个设置项构成的。

entry

设置要打包的文件的进口;能够设置多个进口文件,下面会有引见。

resolve

设置文件后缀名(extensions),除了js,另有jsx、coffee等等。
alias设置项,能够为经常使用模块设置改属性,能够节约编译的搜刮时刻。比方:

    resolve:{
        extensions:['.js','.jsx'],
        alias:{
            'react':path.join(nodeModulesPath,'react/react.js')
        }
    }

除了这个功用还能够设置其他有效的功用,由于我还不完整相识,有晓得的朋侪迎接指教。

output

设置输出文件的途径,文件名等。

module(loaders)

设置要运用的loader。把资本文件(css、图片、html等非js模块)处置惩罚成响应的js模块,然后别的的plugins才能对这些资本举行下一步处置惩罚。比方babel-loader能够把es6的文件转换成es5。
大部分的对文件的处置惩罚的功用都是经由过程loader完成的。loader能够用来处置惩罚在进口文件中require的和其他体式格局援用进来的文件。loader平常是一个自力的node模块,要零丁装置。

loader设置项:

test: /\.(js|jsx)$/,           //注重是正则表达式,不要加引号,婚配要处置惩罚的文件
loader: 'eslint-loader',       //要运用的loader,"-loader"能够省略
include: [path.resolve(__dirname, "src/app")],   //把要处置惩罚的目次包括进来
exclude: [nodeModulesPath]     //消除不处置惩罚的目次

现在已有的loader列表:https://webpack.github.io/docs/list-of-loaders.html

一个module的例子:

module: {
    preLoaders: [
      {
        test: /\.(js|jsx)$/,
        loader: 'eslint-loader',
        include: [path.resolve(__dirname, "src/app")],
        exclude: [nodeModulesPath]
      },
    ],
    loaders: [
      {
        test: /\.(js|jsx)$/, //正则表达式婚配 .js 和 .jsx 文件
        loader: 'babel-loader?optional=runtime&stage=0',//对婚配的文件举行处置惩罚的loader 
        exclude: [nodeModulesPath]//消除node module中的文件
      }
    ]
}

plugins

望文生义,就是设置要运用的插件。plugin是比loader功用更壮大的插件,能运用更多的wepack api。来看一个运用plugin的例子:

plugins: [
    //紧缩打包的文件
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        //supresses warnings, usually from module minification
        warnings: false
      }
    }),
    //许可毛病不打断递次
    new webpack.NoErrorsPlugin(),
    //把指定文件夹xia的文件复制到指定的目次
    new TransferWebpackPlugin([
      {from: 'www'}
    ], path.resolve(__dirname,"src"))
  ]

现在已有的plugins列表:http://webpack.github.io/docs/list-of-plugins.html

怎样紧缩输出的文件

plugins: [
    //紧缩打包的文件
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        //supresses warnings, usually from module minification
        warnings: false
      }
    })]

怎样copy目次下的文件到输出目次

copy文件须要经由过程插件”transfer-webpack-plugin”来完成。

装置:

npm install transfer-webpack-plugin  -save

设置:

var TransferWebpackPlugin = require('transfer-webpack-plugin');
//其他节点省略    
plugins: [
    //把指定文件夹下的文件复制到指定的目次
    new TransferWebpackPlugin([
      {from: 'www'}
    ], path.resolve(__dirname,"src"))
  ]

打包javascript模块

支撑的js模块化计划包括:

  • ES6 模块

    import MyModule from './MyModule.js';
  • CommonJS

    var MyModule = require('./MyModule.js');
  • AMD

    define(['./MyModule.js'], function (MyModule) {
    });

上面已演示了打包js模块,这里不再反复。ES6的模块须要设置babel-loader来先把处置惩罚一下js文件。
下面展现下打包ES模块的设置文件:


var webpack = require('webpack');
var path = require('path');
var buildPath = path.resolve(__dirname, 'build');
var nodeModulesPath = path.resolve(__dirname, 'node_modules');
var TransferWebpackPlugin = require('transfer-webpack-plugin');

var config = {
  entry: [path.join(__dirname, 'src/main.js')],
  resolve: {
    extensions: ["", ".js", ".jsx"]
    //node_modules: ["web_modules", "node_modules"]  (Default Settings)
  },
  output: {
    path: buildPath,    
    filename: 'app.js'  
  },
  plugins: [
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      }
    }),
    new webpack.NoErrorsPlugin(),
    new TransferWebpackPlugin([
      {from: 'www'}
    ], path.resolve(__dirname,"src"))
  ],
  module: {
    preLoaders: [
      {
        test: /\.(js|jsx)$/,
        loader: 'eslint-loader',
        include: [path.resolve(__dirname, "src/app")],
        exclude: [nodeModulesPath]
      },
    ],
    loaders: [
      {
        test: /\.js$/, //注重是正则表达式,不要加引号
        loader: 'babel-loader?optional=runtime&stage=0',//babel模块相干的功用请自查,这里不做引见
        exclude: [nodeModulesPath]
      }
    ]
  },
  //Eslint config
  eslint: {
    configFile: '.eslintrc' //Rules for eslint
  },
};

module.exports = config;

打包静态资本

css/sass/less

装置css-loader和style-loader


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

config设置:


var config = {
    entry:path.resolve(__dirname,'src/main.js'),
    resolve:{
        extentions:["","js"]
    },
    output:{
        path:buildPath,
        filename:"app.js"
    },
    module:{
        loaders:[{
            test:/\.css$/,
            loader:'style!css',//sass设置:style!css!sass 实行递次:左<--右
            exclude:nodemodulesPath
        }]
    }
}

style-loader会把css文件嵌入到html的style标签里,css-loader会把css按字符串导出,这两个基础都是组合运用的。打包完成的文件,援用实行后,会发明css的内容都插进去到了head里的一个style标签里。
假如是sass或less设置体式格局与上面相似。

images

能够经由过程url-loader把较小的图片转换成base64的字符串内嵌在天生的文件里。
装置:


npm install url-loader --save -dev

config设置:

var config = {
    entry:path.resolve(__dirname,'src/main.js'),
    resolve:{
        extentions:["","js"]
    },
    output:{
        path:buildPath,
        filename:"app.js"
    },
    module:{
        loaders:[{
            test:/\.css$/,
            loader:'style!css',//
            exclude:nodemodulesPath
        },
        { test:/\.png$/,loader:'url-loader?limit=10000'}//限定大小小于10k的
        ]
    }
}

css文件内容:


#container{
    color: #f00;
    background:url(images/logo-201305.png);
    /*天生完图片会被处置惩罚成base64的字符串 注重:不要写'/images/logo-201305.png',不然图片不被处置惩罚*/
}

iconfont

内嵌iconfont的运用要领实在和上述处置惩罚png图片的要领一致。经由过程url-loader来处置惩罚。

config设置:


var config = {
    entry:path.resolve(__dirname,'src/main.js'),
    resolve:{
        extentions:["","js"]
    },
    output:{
        path:buildPath,
        filename:"app.js"
    },
    module:{
        loaders:[{
            test:/\.css$/,
            loader:'style!css',//
            exclude:nodemodulesPath
        },
        { test:/\.(png|woff|svg|ttf|eot)$/,loader:'url-loader?limit=10000'}//限定大小小于10k的
        ]
    }
}

css文件内容:


@font-face {font-family: 'iconfont';
src: url('fonts/iconfont.eot'); /* IE9*/
src: url('fonts/iconfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('fonts/iconfont.woff') format('woff'), /* chrome、firefox */
url('fonts/iconfont.ttf') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
url('fonts/iconfont.svg#iconfont') format('svg'); /* iOS 4.1- */
}

实行打包后会把字体文件都转换成base64字符串内容到文件里.
这里有个头疼的题目,就是每一个浏览器支撑的字体花样不一样,由于把悉数花样的字体打包进去,形成不必要的资本糟蹋。

打包template

我以打包handlebars的模块为例,来演示下打包模块的历程。有的模板对应的loader,有能够没有现成的,恐怕要本身完成loader。

先装置必需的node模块

npm install handlebars-loader --save -dev
npm install handlebars -save//是必需的

config设置:


var config = {
    entry:path.resolve(__dirname,'src/main.js'),
    resolve:{
        extentions:["","js"]
    },
    output:{
        path:buildPath,
        filename:"app.js"
    },
    module:{
        loaders:[
        { test: /\.html$/, loader: "handlebars-loader" }
        ]
    }
}

新建一个模板文件tb.html,目次构造:

webpack
    |---index.html
    |---webpack-config.js
    |---src
         |---template
         |         |---tb.html
         |---main.js

main.js中挪用模块的代码以下:


var template = require("./template/tp.html");
var data={say_hello:"it is handlebars"};
var html = template(data);
document.getElementById('tmpl_container').innerHTML = html;         

公用的模块离开打包

这须要经由过程插件“CommonsChunkPlugin”来完成。这个插件不须要装置,由于webpack已把他包括进去了。
接着我们来看设置文件:

var config = {
    entry:{app:path.resolve(__dirname,'src/main.js'),
            vendor: ["./src/js/common"]},//【1】注重这里
    resolve:{
        extentions:["","js"]
    },
    output:{
        path:buildPath,
        filename:"app.js"
    },
    module:{
        loaders:[{
            test:/\.css$/,
            loader:'style!css',
            exclude:nodemodulesPath
        }
        ]
    },
    plugins:[
        new webpack.optimize.UglifyJsPlugin({
             compress: {
                warnings: false
             }
        }),
        //【2】注重这里  这两个处所市用来设置common.js模块零丁打包的
        new webpack.optimize.CommonsChunkPlugin({
            name: "vendor",//和上面设置的进口对应
            filename: "vendor.js"//导出的文件的称号
        })
    ]
}

目次构造如今是如许的:


webpack
  |---index.html
  |---webpack-config.js
  |---src
     |---main.js
     |---js
          |---a.js    //a内里require了common
          |---common.js

实行webpack会天生app.js和common.js两个文件.

code split(模块星散,按需加载)

有些场景,我们能够愿望模块在须要的时刻再加载,而不是一古脑儿打包到一同。从而加快首屏的加载速率。举个例子,在做单页运用的时刻,每一个场景对应一个模块。假如场景许多,把模块打包到一同,末了的bundle文件必定很痴肥,加载很慢。那末只要在每一个场景须要展现的时刻,再加载对应的js模块。就能够优化这个题目了。webpack支撑模块按需加载,这个功用叫code split。下面引见怎样运用这个功用。

目次构造:


webpack
  |---index.html
  |---webpack-config.js
  |---src
     |---main.js
     |---js
          |---codeSplit.js
          

codeSplit.js:


//就是一般的模块 没什么特别的
console.log('code split');

module.exports = {
    name:'cplll'
}             

main.js:

var cp = function(resolve){
     require.ensure(['./js/codeSplit.js'],function(){//注重这里哦,就是用require.ensure来按需加载的,这是webpack特有的
        resolve(require('./js/codeSplit.js'));//加载好 require模块
    });
}

var getModule = function(){
    return new Promise((resolve,reject)=>{
        cp(resolve);
    });
}

getModule().then((cl)=>{
    console.log(cl.name);
});

config设置:

//...省略
var buildPath = path.resolve(__dirname,"build");
var config = {    
    entry:{
        m1:path.resolve(__dirname,'src/main.js')
    },//注重在这里增加文件的进口
    resolve:{
        extentions:["","js"]
    },
    output:{
        path:buildPath,
        filename:"app.js",
        publicPath:'build/' //注重这里哦,星散出来的模块会按这个途径来加载
    }    
}

实行敕令:

webpack --config webpack-config.js --colors

天生效果:

webpack
  |---index.html
  |---webpack-config.js
  |---build //天生效果
  |    |---app.js
  |    |---1.app.js
  |---src
     |---main.js
     |---js
          |---codeSplit.js

页面里援用

<script type="text/javascript" src="./build/app.js"></script>

翻开页面就是发明,app.js和1.app.js(在cp函数挪用的时刻加载)离开加载了。
《WebPack1.x 经常使用功用引见》

末了须要特别注重,设置output里的publicPath。这里轻易有坑。由于不设置加载途径是如许的:

http://localhost:9527/1.app.js

设置今后(publicPath:’build/’):

http://localhost:9527/build/1.app.js

多个进口

config设置:

var config = {    
    entry:{
        m1:path.resolve(__dirname,'src/main.js'),
         m2:path.resolve(__dirname,'src/main1.js')
    },//注重在这里增加文件的进口
    resolve:{
        extentions:["","js"]
    },
    output:{
        path:buildPath,
        filename:"[name].js"//注重这里运用了name变量
    }    
}

webpack-dev-server

在开辟的历程当中个,我们一定不愿望,每次修正完都手动实行webpack敕令来调试递次。所以我们能够用webpack-dev-server这个模块来庖代烦人的实行敕令。它会监听文件,在文件修正后,自动编译、革新浏览器的页面。别的,编译的效果是保留在内存中的,而不是实体的文件,所以是看不到的,由于如许会编译的更快。它就想到与一个轻量的express服务器。
装置:


npm install webpack-dev-server --save -dev

config设置:


var config = {
    entry:path.resolve(__dirname,'src/main.js'),
    resolve:{
        extentions:["","js"]
    },
    //Server Configuration options
    devServer:{
        contentBase: '',  //静态资本的目次 相对途径,相对于当前途径 默以为当前config地点的目次
        devtool: 'eval',
        hot: true,        //自动革新
        inline: true,    
        port: 3005        
    },
    devtool: 'eval',
    output:{
        path:buildPath,
        filename:"app.js"
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),//开启热替代插件
        new webpack.NoErrorsPlugin()
    ]
}

我的目次构造:


webpack
  |---index.html
  |---webpack-config.js//我把静态资本目次设置在了这里
  |---src
     |---main.js
     |---js
          |---a.js
          |---common.js

实行敕令:


webpack-dev-server --config webpack-dev-config.js  --inline --colors

默许接见地点:

http://localhost:3000/index.html(依据设置会不一样)

有一点须要声明,在index.html(援用导出效果的html文件)里直接援用“app.js”,不要加父级目次,由于此时app.js在内存里与output设置的目次无关:

<script type="text/javascript" src="app.js"></script>

细致文档在这里检察:http://webpack.github.io/docs/webpack-dev-server.html

Hot Module Replacement

热替代是指在运用运转时刻替代、增加、移除某个模块而不须要悉数模块从新编译、全部页面从新加载。在web运用变的愈来愈庞杂的本日,webpack的编译速率会愈来愈慢。运用热替代能大大提高webpack的编译速率,提拔开辟效力。下面引见怎样基于webpack-dev-server设置热替代。

config设置:


var config = {
    entry:[
        'webpack/hot/dev-server',//注重点1:热替代设置点1
        path.resolve(__dirname,'src/main1.js')
    ],
    // entry:{m1:path.resolve(__dirname,'src/main.js'),
    //     m2:path.resolve(__dirname,'src/main1.js')},
    resolve:{
        extentions:["","js"]
    },
    // target: 'node',
    //Server Configuration options
    devServer:{
        contentBase: '',  //Relative directory for base of server
        devtool: 'eval',
        hot: true,        //注重点2:热替代设置点2
        inline: true,
        port: 3005        //Port Number
    },
    devtool: 'eval',
    output:{
        path:buildPath,
        filename:"app.js"
    },
    plugins: [
        //Enables Hot Modules Replacement
        new webpack.HotModuleReplacementPlugin(),//注重点3:热替代设置点3
        //Allows error warnings but does not stop compiling. Will remove when eslint is added
        new webpack.NoErrorsPlugin()
    ],
}

设置文件里增加3个设置点

  1. entry 节点里增加 ‘webpack/hot/dev-server’

  2. devServer节点里增加 hot: true

  3. plugins 节点里 new webpack.HotModuleReplacementPlugin()

如许设置文件就设置好了。接下来在代码文件里增加热替代要监听的模块。代码以下:

var h1 = require('./hot1');
if(module.hot){//推断是不是开启了热替代
    module.hot.accept('./hot1',function(){//在hot1模块更新时,实行替代
        h1 = require('./hot1');
    });
}

更多信息参考:webpack-dev-server和热替代引见

怎样区离开辟及临盆环境

在webpack.config.js运用process.env.NODE_ENV举行推断
在package.json内里的script设置环境变量,注重mac与windows的设置体式格局不一样

"scripts": {
    "publish-mac": "export NODE_ENV=prod&&webpack -p --progress --colors",
    "publish-win":  "set NODE_ENV=prod&&webpack -p --progress --colors",
    "dev-mac": "export NODE_ENV=dev&&webpack-dev-server",
    "dev-win":  "set NODE_ENV=dev&&webpack-dev-server
}

config设置:


//其他代码省略...
var NODE_ENV = process.env.NODE_ENV;

var config = {
    //进口文件设置
    entry: path.resolve(__dirname, 'src/main.js'),
    resolve: {
        extentions: ["", "js"]//当requrie的模块找不到时,增加这些后缀
    },
    devtool: 'eval',
    //文件导出的设置
    output: {
        path: buildPath,
        filename: "app.js"
    },
    
    module: {
        loaders: [
            {
                test: /\.html$/, 
                loader: 'tmodjs',//对婚配的文件举行处置惩罚的loader 
                exclude: [nodemodulesPath]//消除node module中的文件
            }
        ]
    }
}

if(NODE_ENV === "prod"){//推断是临盆环境实行临盆设置
    delete config.devtool;
    config.plugins = [
    //紧缩打包的文件
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        //supresses warnings, usually from module minification
        warnings: false
      }
    })];
}

以后dev环境实行敕令:npm run dev-win
临盆环境实行敕令:npm run publish-win

经常使用plugins

  • 代码热替代, HotModuleReplacementPlugin

  • 将css成生文件,而非内联,ExtractTextPlugin

  • 报错但不退出webpack历程,NoErrorsPlugin

  • 多个 html共用一个js文件(chunk),可用CommonsChunkPlugin

  • 清算文件夹,Clean

  • 挪用模块的别号ProvidePlugin,比方想在js顶用$,假如经由过程webpack加载,须要将$与jQuery对应起来

参考文章

webpack运用优化

    原文作者:tinybear
    原文地址: https://segmentfault.com/a/1190000004172052
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞