webpack入门

1.为什么要使用webpack

现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包。为了简化开发的复杂度,前端社区涌现出了很多好的实践方法。

1.模块化,让我们可以把复杂的程序细化为小的文件;

2.Scss,less等CSS预处理器。

3.转换es6语法的处理器等等。

这些改进确实大大的提高了我们的开发效率,但是利用它们开发的文件往往需要进行额外的处理才能让浏览器识别,而手动处理又是非常繁琐的,这就为WebPack类的自动化工具的出现提供了需求。

2.什么是webpack

WebPack可以看做是模块打包机

在 webpack 里,所有类型的文件都可以是模块,包含我们最常见的 JavaScript,以及 css 文件、图片、json 文件等等。通过 webpack 的各种加载器,我们可以更有效地管理这些文件。它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。

3.WebPack和Grunt以及Gulp相比有什么特性

其实Webpack和另外两个并没有太多的可比性,Gulp/Grunt是一种能够优化前端的开发流程的工具,而WebPack是一种模块化的解决方案,模块化是其他构件工具没有的。gulp/grunt能做的,webpack也可以做。所以Webpack的优点(模块化)使得Webpack可以替代Gulp/Grunt类的工具。

Grunt和Gulp的工作方式是:在一个配置文件中,指明对某些文件进行类似编译,组合,压缩等任务的具体步骤,这个工具之后可以自动替你完成这些任务。

Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个浏览器可识别的JavaScript文件。

4.使用webpack

//全局安装
npm install -g webpack
//安装到你的项目目录
npm install --save-dev webpack

正式使用Webpack前的准备

1.建立新文件夹(本例命名为testwebpack)

2.在文件夹里面使用npm init 创建package.json

{
    "name": "webpackee",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "author": "",
    "license": "ISC",

}

注:name值不能和所安装的包重名,否则安装失败。所以本例用在webpack后面随便加了两个字母ee

3.使用npm install --save-dev命令安装webpack,安装完成后如下

{
  "name": "webpackee",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^2.6.1"
  }
}

4.在testwebpack文件中创建两个文件夹(src文件夹和public文件夹),

1.src文件夹放原始数据和我们将写的JavaScript模块、路由模块等等
2.public文件夹用来存放准备给浏览器读取的数据(包括使用webpack生成的打包后的js文件以及一个index.html文件)

5.创建三个文件,index.html 文件放在public文件夹中,两个js文件(Greeter.js和main.js)放在src文件夹中。

index.html文件只有最基础的html代码,它唯一的目的就是加载打包后的js文件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Webpack Sample Project</title>
  </head>
  <body>
    <div id='root'>
    </div>
    <script src="bundle.js"></script>
  </body>
</html>

greeter.js只包括一个用来返回包含问候信息的html元素的函数。

// greeter.js
module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = "Hi there and greetings!";
  return greet;
};

main.js用来把Greeter模块返回的节点插入页面。

//main.js 
var greeter = require('./Greeter.js');
document.getElementById('root').appendChild(greeter());

通过配置文件来使用Webpack

1.在testwebpack文件中新建一个名为webpack.config.js的文件,并在其中进行最最简单的配置,如下所示,它包含入口文件路径和存放打包后文件的地方的路径。

module.exports = {
  entry:  __dirname + "/src/main.js",//唯一入口文件
  output: {
    path: __dirname + "/public",//打包后的文件存放的地方供src引入加载
    filename: "bundle.js"//打包后输出文件的文件名
  }
}

2.通过webpack 命令将文件打包到public文件夹中

$ webpack

3.也可以在package.json中配置脚本命令取代默认的webpack命令。

"scripts": {
    "start": "webpack" //配置的地方就是这里啦,相当于把npm的start命令指向webpack命令
  },

:npm的start是一个特殊的脚本名称,它的特殊性表现在,在命令行中使用npm start就可以执行相关命令,如果对应的此脚本名称不是start,想要在命令行中运行时,需要这样用npm run scriptname如npm run build。

5.生成Source Maps(使调试更容易)

开发总是离不开调试,如果可以更加方便的调试当然就能提高开发效率,不过网页预览的代码一般和开发的代码不一样,比如scss文件网页预览的为css文件。为了可以直接预览scss等文件,方便调试的Source Maps便出现了。

在webpack的配置文件中配置source maps,需要开启谷歌的devtool工具,f12-setting-Enable JavaScript source maps/Enable CSS source maps.

在本例中,随便写错一处代码,如

// greeter.js
    module.exports = function() {
      var greet = document.createElement('div');
      greet.textContent = "Hi there and greetings!";
      return greete;
    };

本来应该返回greet,我加了一个e,肯定会报错。但要是不用source maps,调试时候会显示如下

上面只能定位到bundle这个js,不能定位到greeter.js这个文件,但使用了source maps,调试的时候显示如下:

点击greeter.js可直接跳到错误处。

webpack配置source maps可在webpack.config.js添加devtool选项即可

module.exports = {
    entry:  __dirname + "/src/main.js",//唯一入口文件
    output: {
      path: __dirname + "/public",//打包后的文件存放的地方供src引入加载
      filename: "bundle.js"//打包后输出文件的文件名
    },
    devtool: 'source-map',//配置生成Source Maps,选择合适的选项
 }

具体配置如下:

6.使用webpack构建本地服务器

想不想让你的浏览器监测你的代码的修改,并自动刷新修改后的结果,其实Webpack提供一个可选的本地开发服务器,这个本地服务器基于node.js构建,可以实现你想要的这些功能,不过它是一个单独的组件,在webpack中进行配置之前需要单独安装它作为项目开发依赖。

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

然后在脚本命令行添加快捷命令:

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start":"webpack",
    "server": "webpack-dev-server" //启动命令
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^2.6.1",
    "webpack-dev-server": "^2.4.5"
  }
}

在webpack.config.js中配置服务器

 devServer: {
        contentBase: "./public", //本地服务器所加载的页面所在的目录
       open : true, //打开浏览器
        port: 9000 //端口
  }

其他配置可以参考官网 https://doc.webpack-china.org/configuration/dev-server/

7.Loaders

Loaders是webpack中最让人激动人心的功能之一了。通过使用不同的loader,webpack通过调用外部的脚本或工具可以对各种各样的格式的文件进行处理,比如说分析JSON文件并把它转换为JavaScript文件,或者说把下一代的JS文件(ES6,ES7)转换为现代浏览器可以识别的JS文件。或者说对React的开发而言,合适的Loaders可以把React的JSX文件转换为JS文件。

Loaders需要单独安装并且需要在webpack.config.js下的modules关键字下进行配置.

注:webpack2.0之前的版本是按如下方式配置的

module: {
  loaders: {...}
}

2.0之后的版本是按在rule配置的,不多目前两种方式都支持,以后会逐渐用第二种。

module: {
  rules:[]
}

Loaders的配置选项包括以下几方面:

1.test:接收一个匹配loaders所处理的文件的拓展名的正则表达式(必须),格式为

test: /\.json$/   //匹配json格式文件

2.loader:应用loader的名称(必须),格式为:

module: {
  rules:[
         {
            test: /\.vue$/,
            loader: "json-loader"
          },
        {
            test: /\.js$/,
            loader: ['babel-loader'],
         },
    ]
}

webpack2以后为了更清晰支持 -loader省略的。但测试不能省略

应用多个 loader 和选项时候可以用use属性(数组)

 module: {
    rules: [{
        test: /\.vue$/,
        use: ['vue-loader']
      },
      {
        test: /\.js$/,
        use: ['babel-loader'],
        exclude: /node_modules/
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader', 'postcss-loader']
      },
      {
        test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/,
        use: [{
          loader: 'url-loader',
          options: {
            limit: 10000
          }
        }]
      }
    ]
  },

1.babel

Babel其实是几个模块化的包,其核心功能位于称为babel-core的npm包中。对于每一个你需要的功能或拓展,你都需要安装单独的包(用得最多的是解析Es6的babel-preset-es2015包和解析JSX的babel-preset-react包)

我们先来一次性安装这些依赖包

// npm一次性安装多个依赖模块,模块之间用空格隔开
npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react

然后在webpack中配置

 module: {  
    rules: [{
            test: /\.(png|jpg)$/,
            use: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
        }, {
            test: /\.json$/,
            use: ['json-loader']
        }, {
            test: /\.js$/,
            use: ['babel-loader'], //配置babel
            
        }

    ]
},

然后在和webpack.config.js同级的目录中建立 .babelrc 文件,命令如下

touch .babelrc

webpack会自动调用.babelrc里的babel配置选项。babelrc里面的内容如下:

{
    "presets": ["es2015"]
}

现在就可以使用es6语法了,更改greeter.js文件内容

// greeter.js

var img = require('./assets/cat01.png');
var config = require('./config.json');

//es5

// module.exports = function() {
//     var greet = document.createElement('div');

//     greet.innerHTML = "Hi there and greetings![图片上传失败...(image-e75b6-1519957547350)]" + config.greetText + "";
//     return greet;
// };


//es6
function fn() {
    
    let greet = document.createElement('div');
    greet.innerHTML = "Hi there and greetings![图片上传失败...(image-a3fe33-1519957547350)]" + config.greetText + "";
    return greet;
};
export {fn}; //导出

更改main.js文件内容

//main.js 

// var greeter = require('./greeter.js'); //es5
import { fn } from './greeter.js' //es6 导入
document.getElementById('root').appendChild(fn());

注:import和export必须配对使用,不能在greeter里面使用import,main里面还使用require导入,同理module.exports和require一起使用

开启服务器

即可看到编译成功。

注:主流浏览器支持大部分es6语法(比如本例的import和export),所以不用babel时候也可以编译成功,经本地测试ie10不支持let,所以本例用此命令编译,ie10浏览器不显示此js返回的内容,但使用了babel,ie10就可以看见此js返回的内容

8.万物皆模块

Webpack有一个不可不说的优点,它把所有的文件都可以当做模块处理,包括你的JavaScript代码,也包括CSS和fonts以及图片等等等,只有通过合适的loaders,它们都可以被当做模块被处理。

css加载

webpack提供两个工具处理样式表,css-loader 和 style-loader,二者处理的任务不同。

css-loader:将css文件打包到js文件中,这样才可以使用require或者import导入。

style-loader:将js文件中的css渲染到页面中,在head标签里面。

先安装这两个loader

//安装
npm install --save-dev style-loader css-loader

配置

//使用
{
    test: /\.css$/,
    use: ['style-loader','css-loader'],
}

注:loader的加载顺序都是从右向左的,即先加载css-loader,再加载style-loader,不能颠倒,先加载进入js再渲染页面。颠倒会报错

结果如下


sass使用

先安装sass-loader和node-sass

npm install --save-dev sass-loader node-sass

因为sass-loader依赖于node-sass,所以需要安装node-sass,不安装会报错。

配置

module: {  
    rules: [{
            test: /\.(png|jpg)$/,
            use: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
        }, {
            test: /\.json$/,
            use: ['json-loader']
        }, {
            test: /\.js$/,
            use: ['babel-loader'],
            exclude: /node_modules/,  // 解析时排除的文件夹(node_modules里面也有很多js,但需要排除)

        }, {
            test: /\.scss$/,
            use: ['style-loader','css-loader','sass-loader'],

        }

    ]
},

main.js引入scss文件

import './index.scss'

编译,sass-loader会自动把scss文件编译成css,最后style-loader将其插入style里面


打包css

使用上面的loader,最后css会打包在js里面从而渲染在页面中,但要是不想打包在js中,想把css分离出来。就需要插件了。

安装extract-text-webpack-plugin插件

npm install --save-dev extract-text-webpack-plugin

在webpack.config.js中先引入后插件然再配置

页面顶端定义:

const ExtractTextPlugin = require('extract-text-webpack-plugin');

在loader里面定义

module: {  
    rules: [{
            test: /\.(png|jpg)$/,
            use: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
        }, {
            test: /\.json$/,
            use: ['json-loader']
        }, {
            test: /\.js$/,
            use: ['babel-loader'],
            exclude: /node_modules/,  // 解析时排除的文件夹(node_modules里面也有很多js,但需要排除)

        }, {
            test: /\.scss$/,
            // use: ['style-loader','css-loader','sass-loader'], //打包进js
            use: ExtractTextPlugin.extract({
                fallback: "style-loader",
                use: ["css-loader",'sass-loader'] 
            })
        }

    ]
},

配置插件

plugins: [
    new ExtractTextPlugin("css/index.css"),

]

注:css/index.css 表示css的路径,名字可以随便取,这里取名为index.css。启动服务器的时候并不会在本地生成css文件夹和index.css,而是在服务器新生成的html中自动插入link标签引入此路径下的css

本地的页面结构如下

开启服务器后的预览页面

现在开始测试打包

当输入打包命令后,如果在项目中有public文件夹,会在生成的html添加link连接样式表,并且生成上面自己的路径(css/index)。如果没有public文件夹(文件出口),会自动生成一个public文件夹


打包html

默认情况下,我们在public文件夹中新建一个index.html文件,这样打包后引入js。但要是不想在public建页面,在其他文件夹(比如src文件夹)新建页面,打包时再生成打包后的html。所以

安装插件

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

配置

 plugins: [

    //这里开始写
   new HtmlWebpackPlugin({
        template: 'src/index.html', //文件路径
        inject: 'body' //打包之后的js插入文档的位置 (body表示script标签的位置在body里面的最下面即</body>上面)

    }),

]

在src文件夹新建index.html

启动服务器

同css一样,本地页面无js添加,预览页面会自动添加js

打包

同css一样,无public,生成public文件夹新增index.html,内容自动添加script标签,有public文件夹,直接新增index.html,内容自动添加script标签


引入并打包img

安装url-loader或者file-loader

url-loader和file-loader 都是用于打包文件和图片,但是这2个加载器区别如下

一般限制小图片转 base64 可以用 url-loader,其他情况都用 file-loader。
url-loader应该是file-loader上加了一层过滤。本例中使用url-loader,但两者存在依赖关系,需全部安装才可使用。

安装

 install url-loader file-loader --save-dev

配置

module: {
  rules: [
        {
          test: /\.(png|jpg)$/,
          use: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
        }
      ]
}    

test 属性代表可以匹配的图片类型,除了 png、jpg 之外也可以添加 gif 等,以竖线隔开即开。

limit 字段代表图片打包限制,指当图片大小小于限制时会自动转成 base64 码引用。

name 字段指定了打包后,在打包根目录(output.path)下生成名为 images 的文件夹,并在原图片名前加上8位 hash 值。

在greeter.js中引用

var imgurl = require('./assets/cat01.png');

然后就可以将字符串进行拼接使用了

所有配置

const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
    entry: __dirname + "/src/main.js", //唯一入口文件
    output: {
        path: __dirname + "/public", //打包后的文件存放的地方供src引入加载
        filename: "bundle.js" //打包后输出文件的文件名
    },
    devtool: 'eval-source-map', //配置生成Source Maps,选择合适的选项
    devServer: {
        contentBase: "./src", //本地服务器所加载的页面所在的目录
        open: true,
        compress: true
            // colors: true, //终端中输出结果为彩色
            // historyApiFallback: true, //不跳转
            // inline: true, //实时刷新
            // port: 9000
    },
    module: {  
        rules: [{
                test: /\.(png|jpg)$/,
                use: 'url-loader?limit=8192&name=images/[hash:8].[name].[ext]'
            }, {
                test: /\.json$/,
                use: ['json-loader']
            }, {
                test: /\.js$/,
                use: ['babel-loader'],
                exclude: /node_modules/,  // 解析时排除的文件夹(node_modules里面也有很多js,但需要排除)

            }, {
                test: /\.scss$/,
                // use: ['style-loader','css-loader','sass-loader'],
                use: ExtractTextPlugin.extract({
                    fallback: "style-loader",
                    use: ["css-loader",'sass-loader']
                })
            }

        ]
    },
    plugins: [

        //这里开始写
        new HtmlWebpackPlugin({
            template: 'src/index.html', //文件路径
            inject: 'body' //打包之后的js插入文档的位置

        }),
        new ExtractTextPlugin("css/index.css"),

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

推荐阅读更多精彩内容

  • 无意中看到zhangwnag大佬分享的webpack教程感觉受益匪浅,特此分享以备自己日后查看,也希望更多的人看到...
    小小字符阅读 8,080评论 7 35
  • 我们实现功能丰富的应用,拥有复杂的js代码和一大堆依赖包,模块化,less等css预处理。 这些改进确实大大提供了...
    雪夜酱阅读 257评论 0 0
  • 最近在学习 Webpack,网上大多数入门教程都是基于 Webpack 1.x 版本的,我学习 Webpack 的...
    My_Oh_My阅读 8,090评论 40 247
  • GitChat技术杂谈 前言 本文较长,为了节省你的阅读时间,在文前列写作思路如下: 什么是 webpack,它要...
    萧玄辞阅读 12,609评论 7 110
  • 这本书到了很久,一直没有看,因为有听电台讲述里面的故事。看完整本书,粗略的看与张嘉佳的《从你的世界走过》类似,张嘉...
    奋斗的麦芒阅读 1,354评论 1 10