webpack 使用详解

一、简介

  • 本质,webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)
  • 当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。
  • 四个核心:入口(entry)、输出(output)、loader、插件(plugins)

二、简单使用

注:需要node环境和node伴随的包管理工具npm,webpack也可以全局安装以方便使用

2.1 创建一个empty project,npm初始化,会自动创建package.json

npm init -y

安装webpack,经常使用的可以全局安装,尝试的就运行第二条

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

注:全局安装有时候需要权限加sudo

2.2 简单构建项目结构

  1. 创建src文件夹,编写代码所需资源都放在此文件夹下,如js、css、images、less,或者html文件
  2. 创建out文件夹(起名public 或者其他全凭个人爱好),作为打包输出的,当然如果不想HTML文件打包,可以直接放在这个文件夹下面
    注:上两条是一般项目结构,具体文件根据各自所需,以下Demo所需文件
  3. 在out文件夹下创建index.html并引入打包输出的bundle.js
<!-- index.html -->
<!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>
  1. 在src下创建main.js作为入口文件以及main.css,Greeter.js作为测试js文件,Greeter.css作为测试css文件
// Greeter.js
module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = "Hi there and greetings!";
  return greet;
};
//main.js 
const greeter = require('./Greeter.js');
document.querySelector("#root").appendChild(greeter());
/* Greeter.css */
.root {
  background-color: #eee;
  padding: 10px;
  border: 3px solid #ccc;
}
  1. 修改下package.json方便打包,主要注释运行时清除
{
  "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"
  }
}
  1. 在工程目录下创建webpack.config.js webpack配置文件,建议在开发时使用eval-source-map,__dirname全局变量,文件所在的目录
module.exports = {
  devtool: 'eval-source-map',
  entry:  __dirname + "/src/main.js",
  output: {
    path: __dirname + "/out",
    filename: "bundle.js"
  }
}
  1. 打包检查,运行,不报错说明成功,会在out目录下看到bundle.js文件
npm start

2.3 使用webpack构建本地服务器

  1. 安装依赖,如果加-g为全局安装
npm install --save-dev webpack-dev-server
  1. 修改package.json以及webpack.config.js文件
module.exports = {
  devtool: 'eval-source-map',

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

  devServer: {
    contentBase: "./out",//本地服务器所加载的页面所在的目录
    historyApiFallback: true,//不跳转
    inline: true//实时刷新
  } 
}

package.json中添加

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack",
    "server": "webpack-dev-server --open"
  },
  1. 运行,成功会在浏览器中看到index.html页面,control+c会结束运行
npm server
devserver的配置选项 功能描述
contentBase 默认webpack-dev-server会为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录(本例设置到“public"目录)
port 设置默认监听端口,如果省略,默认为”8080“
inline 设置为true,当源文件改变时会自动刷新页面
historyApiFallback 在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html

2.4 Loaders使用

  • Loaders让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)
2.4.1 json文件
  1. 无需添加依赖,webpack2及以上已经内置可处理JSON文件,这里我们无需再添加webpack1.*需要的json-loader
  2. 在src文件夹下添加config.json
{
  "greetText": "Hi there and greetings from JSON!"
}
  1. 修改Greeter.js
var config = require('./config.json');

module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = config.greetText;
  return greet;
};
  1. 运行,看结果
npm start
2.4.2 Babel
  • Babel其实是一个编译JavaScript的平台,让你能使用最新的JavaScript代码(ES6,ES7...),而不用管新标准是否被当前使用的浏览器完全支持,以及使用基于JavaScript进行了拓展的语言,比如React的JSX;
  • babel-core核心包
  • babel-env-preset 解析Es6
  • babel-preset-react 解析JSX
  • 一般一次性安转多个包
  1. 安装依赖
// npm一次性安装多个依赖模块,模块之间用空格隔开
npm install --save-dev babel-core babel-loader babel-preset-env babel-preset-react
  1. 在webpack中配置Babel
module.exports = {
    entry: __dirname + "/src/main.js",//已多次提及的唯一入口文件
    output: {
        path: __dirname + "/out",//打包后的文件存放的地方
        filename: "bundle.js"//打包后输出文件的文件名
    },
    devtool: 'eval-source-map',
    devServer: {
        contentBase: "./out",//本地服务器所加载的页面所在的目录
        historyApiFallback: true,//不跳转
        inline: true//实时刷新
    },
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader",
                    options: {
                        presets: [
                            "env", "react"
                        ]
                    }
                },
                exclude: /node_modules/
            }
        ]
    }
};
  1. 为了测试ES6以及JSX,安装React
npm install --save react react-dom
  1. 修改Greeter.js和main.js,使用React的ES6
//Greeter,js
import React, {Component} from 'react'
import config from './config.json';

export default class Greeter extends Component{
  render() {
    return (
      <div>
        {config.greetText}
      </div>
    );
  }
}

// main.js
import React from 'react';
import {render} from 'react-dom';
import Greeter from './Greeter';

render(<Greeter />, document.getElementById('root'));
  1. 配置在下面,运行,看结果
  • Babel可以在webpack中配置,也可以单独配置,单独的配置文件webpack会自动调用
//webpack 中添加
module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            }
        ]
    }

单独配置需要在工程目录下创建.babelrc文件

//.babelrc
{
  "presets": ["react", "env"]
}
2.4.3 CSS 文件
  • css-loader使你能够使用类似@import 和 url(...)的方法实现 require()的功能
  • style-loader将所有的计算后的样式加入页面中
  1. 安装依赖
npm install --save-dev style-loader css-loader
  1. 修改webpack 配置,在module对象的rules 数组中添加对象
{
                        loader: "style-loader"
                    }, {
                        loader: "css-loader",
                        options: {
                            modules: true, // 指定启用css modules
                            localIdentName: '[name]__[local]--[hash:base64:5]' // 指定css的类名格式
                        }
                    }
  1. css 文件已在前面创建,在main.js中引入该css文件
//main.js
import React from 'react';
import {render} from 'react-dom';
import Greeter from './Greeter';

import './main.css';//使用require导入css文件

render(<Greeter />, document.getElementById('root'));
  1. 运行,看结果
  • CSS module,通过CSS模块,所有的类名,动画名默认都只作用于当前模块
/* Greeter.css */
.root {
  background-color: #eee;
  padding: 10px;
  border: 3px solid #ccc;
}
import React, {Component} from 'react';
import config from './config.json';
import styles from './Greeter.css';//导入

class Greeter extends Component{
  render() {
    return (
      <div className={styles.root}> //使用cssModule添加类名的方法
        {config.greetText}
      </div>
    );
  }
}

export default Greeter
  • CSS预处理器,Sass 和 Less 之类的预处理器是对原生CSS的拓展,它们允许你使用类似于variables, nesting, mixins, inheritance等不存在于CSS中的特性来写CSS,CSS预处理器可以这些特殊类型的语句转化为浏览器可识别的CSS语句
  1. 安装依赖
npm install --save-dev postcss-loader autoprefixer

2.webpack 配置

//webpack.config.js
module.exports = {
    ...
    module: {
        rules: [
            {
                test: /(\.jsx|\.js)$/,
                use: {
                    loader: "babel-loader"
                },
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: "style-loader"
                    }, {
                        loader: "css-loader",
                        options: {
                            modules: true
                        }
                    }, {
                        loader: "postcss-loader"
                    }
                ]
            }
        ]
    }
}
// postcss.config.js
module.exports = {
    plugins: [
        require('autoprefixer')
    ]
}

2.5 插件(Plugins)使用

2.5.1 内置的版本声明的插件
  1. webpack配置
plugins: [
        new webpack.BannerPlugin('版权所有,翻版必究')
    ]
  1. 运行,查看打包结果


    版本声明插件
2.5.2 HtmlWebpackPlugin
  • 把html文件模板打包成html,自动引入js文件
  1. 安装
npm install --save-dev html-webpack-plugin

2.创建 index.tmpl.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Webpack Sample Project</title>
  </head>
  <body>
    <div id='root'>
    </div>
  </body>
</html>
  1. 配置webpack,新建一个输出文件夹out2,如果继续使用out文件夹需要删除下面的文件
...
output: {
        path: __dirname + "/out2",
        filename: "bundle.js"
    },
...
plugins: [
        new webpack.BannerPlugin('版权所有,翻版必究'),
        new HtmlWebpackPlugin({
            template: __dirname + "/app/index.tmpl.html"//new 一个这个插件的实例,并传入相关的参数
        })
    ]
  1. 运行,查看结果,out2文件夹下会出现bundle.js和index.html文件
2.5.3 Hot Module Replacement
  • 简称HMR,自动刷新实时预览修改效果
new webpack.HotModuleReplacementPlugin()//热加载插件
  • HMR是webpack插件,使用时还需要对模块进行额外的配置
  • react-transform-hrm Babel 插件,可以在不对React模块进行额外的配置的前提下让HMR正常工作
npm install --save-dev babel-plugin-react-transform react-transform-hmr
// .babelrc
{
  "presets": ["react", "env"],
  "env": {
    "development": {
    "plugins": [["react-transform", {
       "transforms": [{
         "transform": "react-transform-hmr",
         
         "imports": ["react"],
         
         "locals": ["module"]
       }]
     }]]
    }
  }
}
2.5.4 其他常用插件
  • UglifyJsPlugin 压缩JS代码,内置插件
  • ExtractTextPlugin 分离CSS和JS文件
npm install --save-dev extract-text-webpack-plugin
  • OccurenceOrderPlugin 给组件分配ID,内置插件
        new webpack.optimize.OccurrenceOrderPlugin(),
        new webpack.optimize.UglifyJsPlugin(),
        new ExtractTextPlugin("style.css")
  • clean-webpack-plugin 使用缓存时会把hash值添加到输出文件名,此插件解决缓存的多余文件
    git
npm install  --save-dev clean-webpack-plugin 
const CleanWebpackPlugin = require("clean-webpack-plugin");
...
new CleanWebpackPlugin('build/*.*', {
      root: __dirname,
      verbose: true,
      dry: false
  })
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容