webpack入门学习笔记

webpack学习笔记

什么是Webpack?

WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。

为什么要使用Webpack?

现今的很多网页其实可以看做是功能丰富的应用,它们拥有着复杂的JavaScript代码和一大堆依赖包。为了简化开发的复杂度,就出现了Webpack这种工具。

开始使用Webpack

安装

①进行全局安装

//全局安装
npm install -g webpack

②在项目目录中初始化

//初始化以生成package.js文件
npm init

③在项目目录中局部安装

// 局部安装Webpack
npm install --save-dev webpack

④在项目目录中新建两个文件夹,app文件夹和public文件夹,app文件夹用来存放原始数据和我们将写的JavaScript模块,public文件夹用来存放之后供浏览器读取的文件(包括使用webpack打包生成的js文件以及一个index.html文件)。接下来我们再创建三个文件:

  • index.html --放在public文件夹中;
  • Greeter.js -- 放在app文件夹中;
  • main.js -- 放在app文件夹中;

⑤我们在index.html文件中写入最基础的html代码,它在这里目的在于引入打包后的js文件。(所引入js文件例如本例中的bundle.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元素的函数,并依据CommonJS规范导出这个函数为一个模块:

// Greeter.js
module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = "Hi there and greetings!";
  //这是一个DOM元素
  return greet;
};

main.js文件中写入下述代码,用以把Greeter模块返回的节点插入页面。

//main.js 
const greeter = require('./Greeter.js');
document.querySelector("#root").appendChild(greeter());

正式使用Webpack

通过配置文件来使用Webpack

定义一个配置文件,这个配置文件其实也是一个简单的JavaScript模块,我们可以把所有的与打包相关的信息放在里面。在项目的根目录下新建一个名为webpack.config.js的文件,我们在其中写入如下所示的简单配置代码:

module.exports = {
    //“__dirname”是node.js中的一个全局变量,它指向当前执行脚本所在的目录
    entry:  __dirname + "/app/main.js",//唯一入口文件
    output: {
        path: __dirname + "/public",//打包后的文件存放的地方
        filename: "bundle.js"//打包后输出文件的文件名
    }
}

有了这个配置之后,再打包文件,只需在终端里运行webpack(非全局安装需使用node_modules/.bin/webpack)命令就可以了,这条命令会自动引用webpack.config.js文件中的配置选项。

更快捷地执行打包任务

npm可以引导任务执行,对npm进行配置后可以在命令行中使用简单的npm start命令来替代上面略微繁琐的命令。在package.json中对scripts对象进行相关设置即可,设置方法如下:

{
  "name": "webpack-sample-project",
  "version": "1.0.0",
  "description": "Sample webpack project",
  "scripts": {
    "start": "webpack" // 修改的是这里,JSON文件不支持注释,引用时请清除
  },
  "author": "zhang",
  "license": "ISC",
  "devDependencies": {
    "webpack": "3.10.0"
  }
}

npmstart命令是一个特殊的脚本名称,其特殊性表现在,在命令行中使用npm start就可以执行其对于的命令,如果对应的此脚本名称不是start,想要在命令行中运行时,需要这样用npm run {script name}npm run build

生成source maps(使调试更容易)

对小到中型的项目中,eval-source-map是一个很好的选项,不过需要注意只应该开发阶段使用它(对于打包后输出的JS文件执行具有性能和安全隐患),我们继续对上文新建的webpack.config.js,进行如下配置:

module.exports = {
  devtool: 'eval-source-map',
  entry:  __dirname + "/app/main.js",
  output: {
    path: __dirname + "/public",
    filename: "bundle.js"
  }
}

使用webpack构建本地服务器(使得浏览器实时监听代码修改,并自动刷新显示修改后的结果)

webpack中进行配置之前需要单独安装本地开发服务器

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

然后修改配置文件webpack.config.js

module.exports = {
  devtool: 'eval-source-map',

  entry:  __dirname + "/app/main.js",
  output: {
    path: __dirname + "/public",
    filename: "bundle.js"
  },

  devServer: {
    //端口port要是省略,默认为8080
    contentBase: "./public",//本地服务器所加载的页面所在的目录
    historyApiFallback: true,//不跳转
    inline: true//实时刷新
  } 
}

package.json中的scripts对象中添加如下命令,用以开启本地服务器:

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack",
    "server": "webpack-dev-server --open"
  },

Loaders

Loaders的作用

通过使用不同的loaderwebpack有能力调用外部的脚本或工具,实现对不同格式的文件的处理,比如说分析转换scsscss,或者把下一代的JS文件(ES6,ES7)转换为现代浏览器兼容的JS文件,对React的开发而言,合适的Loaders可以把React的中用到的JSX文件转换为JS文件。

配置Loaders

Babel

什么是Babel?

Babel是一个编译JavaScript的平台

为什么要使用Babel?
  • 让你能使用最新的JavaScript代码(ES6,ES7...),而不用管新标准是否被当前使用的浏览器完全支持;
  • 让你能使用基于JavaScript进行了拓展的语言,比如ReactJSX
Babel的安装与配置

Babel其实是几个模块化的包,其核心功能位于称为babel-core的npm包中,webpack可以把其不同的包整合在一起使用,对于每一个你需要的功能或拓展,你都需要安装单独的包(用得最多的是解析Es6的babel-preset-env包和解析JSXbabel-preset-react包)。

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

然后在webpack中配置Babel:

module.exports = {
    devtool: 'eval-source-map',

    //“__dirname”是node.js中的一个全局变量,它指向当前执行脚本所在的目录
    entry:  __dirname + "/app/main.js",//唯一入口文件
    output: {
        path: __dirname + "/public",//打包后的文件存放的地方
        filename: "bundle.js"//打包后输出文件的文件名
    },

    devServer:{
       contentBase:"./public",
       historyApiFallback:true,
        inline:true
    },

    module:{
        rules:[
            {
                //利用正则表达式匹配jsx和js格式文件
                test:/(\.jsx|\.js)/,
                use:{
                    loader:"babel-loader",
                    options:{
                        preset:[
                            //使得允许解析ES6和JSX语法
                            "env", "react"
                        ]
                    }
                },
                //不处理此文件夹下的文件
                exclude:/node_modules/
            }
        ]
    }
};

Babel其实可以完全在webpack.config.js中进行配置,但是考虑到babel具有非常多的配置选项,在单一的webpack.config.js文件中进行配置往往使得这个文件显得太复杂,因此一些开发者支持把babel的配置选项放在一个单独的名为 .babelrc 的配置文件中。

module.exports = {
    devtool: 'eval-source-map',

    //“__dirname”是node.js中的一个全局变量,它指向当前执行脚本所在的目录
    entry:  __dirname + "/app/main.js",//唯一入口文件
    output: {
        path: __dirname + "/public",//打包后的文件存放的地方
        filename: "bundle.js"//打包后输出文件的文件名
    },

    devServer:{
       contentBase:"./public",
       historyApiFallback:true,
        inline:true
    },

    module:{
        rules:[
            {
                test:/(\.jsx|\.js)/,
                use:{
                    loader:"babel-loader"
                    //将options选项移至.babelrc中
                },
                exclude:/node_modules/
            }
        ]
    }
};
//.babelrc
{
  "presets": ["react", "env"]
}

CSS

CSS配置

webpack提供两个工具处理样式表,css-loaderstyle-loader,二者处理的任务不同,css-loader使你能够使用类似@importurl(...)的方法实现 require()的功能,style-loader将所有的计算后的样式加入页面中,二者组合在一起使你能够把样式表嵌入webpack打包后的JS文件中。
首先进行安装:

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

接着修改webpack.config.js中的配置文件:

module.exports = {
    devtool: 'eval-source-map',

    //“__dirname”是node.js中的一个全局变量,它指向当前执行脚本所在的目录
    entry:  __dirname + "/app/main.js",//唯一入口文件
    output: {
        path: __dirname + "/public",//打包后的文件存放的地方
        filename: "bundle.js"//打包后输出文件的文件名
    },

    devServer:{
       contentBase:"./public",
       historyApiFallback:true,
        inline:true
    },

    module:{
        rules:[
            {
                test:/(\.jsx|\.js)$/,
                use:{
                    loader:"babel-loader"
                    //将options选项移至.babelrc中
                },
                exclude:/node_modules/
            },
            {
                test:/\.css$/,
                use:[
                    {
                        loader:"style-loader"    
                    }, {
                        loader:"css-loader"
                    }
                ]
            }
        ]
    }
};

注意:我们这里例子中用到的webpack只有单一的入口,其它的模块需要通过 import, require, url等与入口文件建立其关联。

CSS module

被称为CSS modules的技术意在把JS的模块化思想带入CSS中来,通过CSS模块,所有的类名,动画名默认都只作用于当前模块。(使CSS拥有局部作用域)
配置:

module.exports = {

    ...

    module:{
        rules:[
            {
                test:/(\.jsx|\.js)$/,
                use:{
                    loader:"babel-loader"
                    //将options选项移至.babelrc中
                },
                exclude:/node_modules/
            },
            {
                test:/\.css$/,
                use:[
                    {
                        loader:"style-loader"    
                    }, {
                        loader:"css-loader",
                        options:{
                            modules:true, //指定启用css modules
                            localIdentName: '[name]__[local]--[hash:base64:5]' //指定css的类名格式
                        }
                    }
                ]
            }
        ]
    }
};

使用:
先将要使用的CSS文件引入,例如:

import styles from './Greeter.css';

然后在需要使用的地方通过以下方式调用:

<div className={styles.root}> //使用cssModule添加类名的方法
CSS预处理器

首先安装postcss-loaderautoprefixer(自动添加前缀的插件)

npm install --save-dev postcss-loader autoprefixer

接下来在webpack.config.js中添加postcss-loader

module.exports = {

    ...

    module:{
             rules:[
                 {
                     test:/(\.jsx|\.js)$/,
                     use:{
                         loader:"babel-loader"
                         //将options选项移至.babelrc中
                     },
                     exclude:/node_modules/
                 },
                 {
                     test:/\.css$/,
                     use:[
                         {
                             loader:"style-loader"    
                         }, {
                             loader:"css-loader",
                             options:{
                                 modules:true, //指定启用css modules
                                 localIdentName: '[name]__[local]--[hash:base64:5]' //指定css的类名格式
                             }
                         }, {
                             loader:"postcss-loader"                    
                         }
                     ]
                 }
             ]
         }
};

再之后在根目录新建postcss.config.js,并添加如下代码之后,重新使用npm start打包,css将会自动添加前缀。

// postcss.config.js
module.exports = {
    plugins: [
        require('autoprefixer')
    ]
}

插件(Plugins)

Plugins和Loaders的区别

Loaders和Plugins常常被弄混,但是他们其实是完全不同的东西,可以这么来说,loaders是在打包构建过程中用来处理源文件的(JSXScssLess..),一次处理一个,插件并不直接操作单个文件,它直接对整个构建过程其作用。

使用插件的方法

要使用某个插件,我们需要通过npm安装它,然后要做的就是在webpack配置中的plugins关键字部分添加该插件的一个实例。(plugins是一个数组)

常用插件
HtmlWebpackPlugin

这个插件的作用是依据一个简单的index.html模板,生成一个自动引用你打包后的JS文件的新index.html。这在每次生成的js文件名称不同时非常有用(比如添加了hash值)。
首先进行插件的安装:

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

安装完成之后,如果是依照以上教程流程部署环境的话,那么就得修改原先的项目结构:

  1. 移除public文件夹,利用此插件,index.html文件会自动生成,此外CSS已经通过前面的操作打包到JS中了。
  2. 在app目录下,创建一个index.tmpl.html文件模板,这个模板包含title等必须元素,在编译过程中,插件会依据此模板生成最终的html页面(如index.tmpl.html),会自动添加所依赖的 css, js,favicon等文件。
  3. 在这之后,需要在webpack.config.js中配置添加的插件:
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {

    ...
    
    module:{
             rules:[
                 {
                     test:/(\.jsx|\.js)$/,
                     use:{
                         loader:"babel-loader"
                         //将options选项移至.babelrc中
                     },
                     exclude:/node_modules/
                 },
                 {
                     test:/\.css$/,
                     use:[
                         {
                             loader:"style-loader"    
                         }, {
                             loader:"css-loader",
                             options:{
                                 modules:true, //指定启用css modules
                                 localIdentName: '[name]__[local]--[hash:base64:5]' //指定css的类名格式
                             }
                         }, {
                             loader:"postcss-loader"                    
                         }
                     ]
                 }
             ]
    },
    plugins:[
        new HtmlWebpackPlugin({
            //传入相关参数
            template:__dirname + "/app/index.tmpl.html"
        })
    ]
};
  1. 新建一个build文件夹存放最终输出文件(需要修改webpack.config.js),然后再次运行npm start就行了。

这篇文章是我参考学习(copy)别人webpack入门教程的时候写下的,写时对文章内容还有不是很理解的地方,需要之后再次阅读。更加具体的内容请参考教程原文:zhangwang的webpack入门教程

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

推荐阅读更多精彩内容

  • 最近在学习 Webpack,网上大多数入门教程都是基于 Webpack 1.x 版本的,我学习 Webpack 的...
    My_Oh_My阅读 8,166评论 40 247
  • 无意中看到zhangwnag大佬分享的webpack教程感觉受益匪浅,特此分享以备自己日后查看,也希望更多的人看到...
    小小字符阅读 8,140评论 7 35
  • 采遍二月玫瑰的露水。 流尽世间痴情人的眼泪。 在菩提树下倾尽精髓 只求得再与你同醉终不悔 不负苦心一别千年今昔见 ...
    晚晴521阅读 152评论 0 0
  • 最近工作之余觉得可以写点东西然后贡献出来,分享给大家。现在APP 都会用到第三方分享功能,但是目前ShareSDK...
    ivylee_mr阅读 2,045评论 0 2
  • 上大学的时候,在卷卷的推荐下看了《魁拔》这部动漫,突然觉得国产动漫崛起有希望了,因此从这以后就喜欢上课这部动漫。...
    夏目心叶阅读 796评论 2 4