webpack 配置学习笔记

webpack 入门 大全学习笔记

  1. 新建文件夹,命名 webpack project,在命令行中找到此位置。使用:
    //全局安装
    npm install webpack -g 
    //安装到项目目录 
    npm install webpacl --save-dev
  1. 在新建package.json 文件,这是一个标准的 npm 说明文件。在命令行输入npm init 即可自动生成本文件(文件生成过程中所需参数均可不填);
  2. 回到之前的空文件夹,并创建 app 与 piblic 两个文件夹。其中 app文件夹存放原始数据和我们将写的JavaScript模块。public 文件夹用来存放之后后浏览器读取的文件(包括使用webpack 打包生成的js文件以及一个 index.html 文件)。接下来再创建三个文件夹中:
    • index.html –放在public文件夹中;
    • Greeter.js –放在app文件夹中;
    • main.js –放在app文件夹中。
      在 index.html 中写入最基本的html代码,它在这里的目的在于引入打包之后的js文件。
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webpack test</title>
</head>
<body>
    <div id="root">

    </div>
    <script type="text/javascript" src="bundle.js"></script>
</body>
</html>

在Greeter.js 中定义一个返回包含问候信息的html元素的函数,并依据 CommonJS规范导出这个函数为一个模块。

//Greete.js
module.exports = function(){
    var greet = document.createElement('div');
    greet.textContent = "Hi this from Greeter.js";
    return greet;
}

在main.js 文件中 引入Greeter.js文件,并添加到html文件中。

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

正式使用 webpack

webpack 可以在终端使用,基本使用方法如下:

# {extry file}出填写入口文件的路径,本文中就是上述main.js的路径,
# {destination for bundled file}处填写打包文件的存放路径
# 填写路径的时候不用添加{}
webpack {entry file} {destination for bundled file}

配置webpack

在练习文件夹下新建 webpack.config.js ,写入一下基本配置:

module.exports = {
    entry:__dirname + "/app/main.js",//入口文件
    output:{
        path:__dirname +"/public/",//打包后的文件存放的地方
        filename:"bundle.js" //打包后输出文件夹的名字
    }
}

设置完毕后,只需在命令行中输入 webpack 执行,即可。
继续对 npm 进行配置后可以在命令行中使用简单的 npm start 命令来替代上述命令。在 package.json文件中 对 scripts对象进行相关设置即可,设置方法如下:

// + 代表新增。- 代表删除
 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
 +   "start":"webpack"
  },

webpack 的强大功能

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

webpack.config.js 中进行配置:

module.exports = {
+   devtool: 'eval-source-map',
    entry: __dirname + "/app/main.js", //入口文件
    output: {
        path: __dirname + "/public/", //打包后的文件存放的地方
        filename: "bundle.js" //打包后输出文件夹的名字
    }
}

使用webpack 构建本地服务器

让浏览器监听你的代码的修改,并自动刷新显示后的结果。安装组件:

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

继续配置 webpack.config.js

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

    entry: __dirname + "/app/main.js", //入口文件
    output: {
        path: __dirname + "/public/", //打包后的文件存放的地方
        filename: "bundle.js" //打包后输出文件夹的名字
    },
+   devServer: {
+       contentBase: "./public/", //本地服务器所加载的页面所在的目录
+       historyApiFallback: true, //不跳转
+       inline: true, //实时刷新
+       //  port:8080 //设置监听端口。默认8080;
    }
}

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

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

在命令行中输入npm run server 即可在本地的8080(默认端口)查看结果。

Loaders

Loaders 需要单独安装并且需要在webpack.config.js 中的 modules 关键字下进行配置。Loaders 的配置包括以下几个方面:
- test:一个用以匹配loaders所处理文件的扩展名的正则表达式(必须);
- loader:loader的名称(必须);
- include/exclude:手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选);
- query:为loaders提供额外的设置选项(可选).

扫描二维码关注公众号,回复: 9650063 查看本文章
不过在配置loader之前,我们把`Greeter.js`里的问候消息放在一个单独的`JSON`文件里,并通过合适的配置使`Greeter.js`可以读取该`JSON`文件的值,各文件修改后的代码如下:
在 public文件中创建如下 JSON 文件(命名为:`config.json`):
{
    "greetText":"Hi this message from /public/config.json"
}

更新后的 Greeter.js

+ var config = require('../public/config.json');
module.exports = function() {
    var greet = document.createElement('div');
+   greet.textContent = config.greetText;
    return greet;
}

Babel 的安装与配置

一次性的安装依赖包:

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

在webpack 中的webpack.config.js 添加如下配置:

+ module: {
+       rules: [{
+           test: /(\.jsx|\.js)$/,
+           use: {
+               loader: "babel-loader",
+               options: {
+                   presets: ["es2015", "react"]
+               }
+           },
+           exclude: /node_modules/
+       }]
+   }

安装 react 以及 reactdom:
接下来使用ES6 的语法,更新Greeter.js,并返回一个React组件:

+ import React,{Component} from 'react'
+ import config from '../public/config.json';

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

修改main.js如下:

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

+ render(<Greeter />, document.getElementById('root'));

重新使用npm start打包,会在http://localhost:8080/看到相应输出。这说明react 和 es6 被正常打包了。

一切皆模块

CSS

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

继续在webpack.config.js中添加module配置:

    module: {
        rules: [{
            。。。},
    +   {
    +       test:/\.css$/,
    +       use:[{
    +           loader:"style-loader"
    +       },{
    +           loader:"css-loader"
    +       }]
    +   }]
    }

接下来,在app文件夹中创建一个名字为“main.css”的文件,设置一些样式:

html{
    box-sizing: border-box;
    -ms-text-size-adjust:100%;
    -webkit-text-size-adjust:100%;
}
*,*:before,*:after{
    box-sizing: inherit;
}
body{
    margin:0;
    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
}
h1,h2,h3,h4,h5,h6,p,ul{
    margin:0;
    padding:0;
}

我们这里例子中用到的webpack只有单一的入口,其它的模块需要通过 import, require, url等与入口文件建立其关联,为了让webpack能找到”main.css“文件,我们把它导入”main.js“中,如下:

//main.js
+ import './main.css'; //导入css文件。

上面的代码说明webpack是怎么把css当做模块看待的,咱们继续看一个更加真实的css模块实践。

CSS module

最近有一个叫做 CSS modules 的技术就意在把JS的模块化思想带入CSS中来,通过CSS模块,所有的类名,动画名默认都只作用于当前模块。Webpack从一开始就对CSS模块化提供了支持,在CSS loader中进行配置后,你所需要做的一切就是把”modules“传递到所需要的地方,然后就可以直接把CSS的类名传递到组件的代码中,且这样做只对当前组件有效,不必担心在不同的模块中使用相同的类名造成冲突。具体的代码如下:

//webpack.config.js
{
            test: /\.css$/,
            use: [{
                loader: "style-loader"
            }, {
                loader: "css-loader",
+               options:{
+                   modules:true
+               }
            }]
        }

继续:
在app文件夹下创建一个Greeter.css文件:

.root{
    background-color: #eee;
    padding:10px;
    border:3px solid #ccc;
}

导入 .rootGreeter.js中:

import React, {Component} from 'react'
import config from '../public/config.json';
+ import styles from './Greeter.css'; //导入css样式
class Greeter extends Component {
    render() {
        return (
+           <div className={styles.root}> 
            {config.greetText}
            </div>
        );
    }
}
export default Greeter

在命令行中打包,在打开index.html文件查看效果。

CSS 预处理器

css 预处理器可以将特殊类型的语句转化为浏览器可识别的CSS语句。
在 webpack 里使用相关 loaders进行配置就可以使用了。以下是常用的CSS 处理loaders:
- Less Loader
- Sass Loader
- Stylus Loader
还有一个 PostCSS,可以帮助CSS实现更多功能。举例来说,使用PostCSS为CSS代码自动添加适应不同浏览器的CSS 前缀。
首先安装postcss-loaderautoprefixer(自动添加前缀的插件)

npm install postss-loader autoprefixer --save-dev

接下来,在webpack 配置文件webpack.config.js中添加postcss-loader,在根目录新建 postcss.config.js,并添加如下代码之后,重新使用 npm start打包时,写的css会自动根据 Can i use 里的数据添加不同前缀了。

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

插件(Plugins)

插件(Plugins)是用来拓展Webpack功能的,它们会在整个构建过程中生效,执行相关的任务。
Loaders和Plugins常常被弄混,但是他们其实是完全不同的东西,可以这么来说,loaders是在打包构建过程中用来处理源文件的(JSX,Scss,Less..),一次处理一个,插件并不直接操作单个文件,它直接对整个构建过程其作用。

使用插件的方法

要使用某个插件,需要使用 npm 安装它,然后要做的就是在 webpack配置中的plugins 关键字部分添加该插件的一个实例(plugins 是一个数组),继续上面的例子。给其添加一个给打包后代码添加版权声明的插件(BannerPlugin

+ const webpack = require('webpack');
 module.exports = {
     。。。
     module:{
     。。。
     },
+    plugins: [
+       new webpack.BannerPlugin('版权所有,翻版必究')
+   ]

}

HtmlWebpackPlugin

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

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

这个插件自动完成了我们之前手动做的一些事情,在正式使用之前需要对一直以来的项目结构做一些更改:
1. 移除public文件夹。利用此插件,index.html文件会自动生成。此外,css已经通过前面的操作打包到js中了。
2. 在app目录下,创建一个 index.tmpl.html 文件模板,这个模板包含 title 等必须元素,在编译过程中,插件会依据此模板生成最终的html 页面,会自动添加所以来的css,js,favicon, index.tmpl.html 中的模板源代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webpack test module</title>
</head>
<body>
        <div id="root">

        </div>
</body>
</html>
  1. 更新webpack的配置文件:添加plugin及其参数,修改output输出文件目录,修改devServer的目录。方法同上,新建一个 build 文件夹用来存放最终的输出文件。
//webpack.config.js
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    。。。
    output: {
+       path: __dirname + "/build/", //打包后的文件存放的地方
        filename: "bundle.js" //打包后输出文件夹的名字
    },
    devServer: {
+       contentBase: "./build/", //本地服务器所加载的页面所在的目录
        historyApiFallback: true, //不跳转
        inline: true, //实时刷新
        //  port:8080 //设置监听端口。默认8080;
    },
    plugins: [
        new webpack.BannerPlugin('版权所有,翻版必究'),
+       new HtmlWebpackPlugin({
+           template: __dirname + "/app/index.tmpl.html" //new 一个这个插件的实例,并传入相关的参数
+       })
    ]
}

修改,app文件夹下的Greeter.js 文件:

- import config from './public/config.json';
+ import config from './config.json';

在本目录新建 config.json ,内同同public文件中中的config.json。
执行 npm start会在build 文件夹下面发现bundle.js index.html两个文件。

Hot Module Replacement

Hot Module Replacement(HMR)也是webpack里很有用的一个插件,它允许你在修改组件代码后,自动刷新实时预览修改后的效果。
在webpack中实现HMR也很简单,只需要做两项配置:
- 在webpack配置文件中添加HMR插件;
- 在 webpack Dev Server中添加“hot”参数;
不过配置完这些后,JS模块其实还是不能自动热加载的,还需要在你的JS模块中执行一个Webpack提供的API才能实现热加载,虽然这个API不难使用,但是如果是React模块,使用我们已经熟悉的Babel可以更方便的实现功能热加载。
整理下我们的思路,具体实现方法如下

Babel和webpack是独立的工具
- 二者可以一起工作
- 二者都可以通过插件拓展功能
- HMR是一个webpack插件,它让你能浏览器中实时观察模块修改后的效果,但是如果你想让它工作,需要对模块进行额外的配额;
- Babel有一个叫做react-transform-hrm的插件,可以在不对React模块进行额外的配置的前提下让HMR正常工作;
继续上例,进行配置:

//webpack.config.js
    devServer: {
        contentBase: "./build/", //本地服务器所加载的页面所在的目录
        historyApiFallback: true, //不跳转
        inline: true, //实时刷新
+       hot:true,
        //  port:8080 //设置监听端口。默认8080;
    },
    plugins: [
        new webpack.BannerPlugin('版权所有,翻版必究'),
        new HtmlWebpackPlugin({
            template: __dirname + "/app/index.tmpl.html" //new 一个这个插件的实例,并传入相关的参数
        }),
+       new webpack.HotModuleReplacementPlugin() //热加载插件
    ]

安装 react-transform-hmr

npm install babel-plugin-react-transform react-transform-hmr --save-dev

由于babel配置增加,所以新建.babelrc 文件来统一babel配置设置。

//.babelrc
{
    "presets":["react","es2015"],
    "env":{
    "development":{
    "plugins":[["react-transform",{
        "transforms":[{
            "transform":"react-transform-hmr",
            "imports":["react"],
            "locals":["module"]
    }]
    }]]
    }
    }
}
//webpack.config.js
rules: [{
            test: /(\.jsx|\.js)$/,
            use: {
                loader: "babel-loader",
-               // options: {
-               //  presets: ["es2015", "react"]
-               // }
            },
            exclude: /node_modules/
        },{...}]

现在当你使用React时,可以热加载模块了,每次保存就能在浏览器上看到更新内容。

产品阶段的构建

目前为止,我们已经使用webpack构建了一个完整的开发环境。
但是在产品阶段,可能还需要对打包的文件进行额外的处理,比如说优化,压缩,缓存以及分离CSS和JS。
对于复杂的项目来说,需要复杂的配置,这时候分解配置文件为多个小的文件可以使得事情井井有条,以上面的例子来说,我们创建一个webpack.production.config.js的文件,在里面加上基本的配置,它和原始的webpack.config.js很像,如下:

// webpack.production.config.js
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry: __dirname + "/app/main.js",//已多次提及的唯一入口文件
    output: {
        path: __dirname + "/build",
        filename: "bundle.js"
    },
    devtool: 'eval-source-map',
    devServer: {
        contentBase: "./public",//本地服务器所加载的页面所在的目录
        historyApiFallback: true,//不跳转
        inline: true,
        hot: true
    },
    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"
                    }
                ]
            }
        ]
    },
    plugins: [
        new webpack.BannerPlugin('版权所有,翻版必究'),
        new HtmlWebpackPlugin({
            template: __dirname + "/app/index.tmpl.html"//new 一个这个插件的实例,并传入相关的参数
        }),
        new webpack.HotModuleReplacementPlugin()//热加载插件
    ],
};
//package.json
{
  "name": "webpackproject",
  "version": "1.0.0",
  "description": "for webpack test",
  "main": "index.js",
  "dependencies": {
    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "webpack": "^3.5.4"
  },
  "devDependencies": {
    "autoprefixer": "^7.1.2",
    "babel-core": "^6.25.0",
    "babel-loader": "^7.1.1",
    "babel-plugin-react-transform": "^2.0.2",
    "babel-preset-es2015": "^6.24.1",
    "babel-preset-react": "^6.24.1",
    "css-loader": "^0.28.4",
    "html-webpack-plugin": "^2.30.1",
    "postcss-loader": "^2.0.6",
    "react-transform-hmr": "^1.0.4",
    "style-loader": "^0.18.2",
    "webpack-dev-server": "^2.7.1"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack",
    "server": "webpack-dev-server --open",
    "build": " set NODE_ENV=production &&webpack --config ./webpack.production.config.js --progress",
  },
  "author": "wang",
  "license": "ISC"
}

优化插件

通过npm安装。一下插件可以完成产品发布阶段所需的功能:
- OccurenceOrderPlugin:为组件分配ID,通过这个插件webpack 可以分析和优先考虑使用最多的模块,并未他们分配最小的ID。
- UglifyJsPlugin:压缩JS代码;
- ExtractTextWebpackPlugin:分离CSS和JS文件;
继续使用上例查看如何添加他们。OccurenceOrder 和 UglifyJS plugins 都是内置插件,你需要做的只是安装其它非内置插件:

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

在配置文件中的plugins后引用他们:

//webpack.production.config.js
const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  module: {
    rules: [
      {
        test: /\.css$/,
+                   use: ExtractTextPlugin.extract({
+                   fallback: "style-loader",
+                   use: [
-                           // {
-                       // loader: "style-loader"
-                       // },{
                        loader: "css-loader",
                        options: {
                            modules: true
                        }
                    }, {
                        loader: "postcss-loader"
                    }]
                })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin("styles.css"),
  ]
}

这是在命令行中运行“npm run build” 可以看到在“build”文件夹下新生成了“style.css”文件。

发布了37 篇原创文章 · 获赞 12 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/peng_9/article/details/77267039
今日推荐