Dean Front-end Dev Engineer

Webpack 的基本使用

2018-03-09

摘要

这篇文章讲述了,如何用webpack + ES6/7 + sass 进行组件化开发,最后生产出兼容的压缩好的 css,js 文件。

先说一下简单的使用

下面例子用的是 webpack4.1.0,不同版本的 webpack 可能会稍有不同。

首先创建一个目录 webpack-test,并cd到目录

第一步:初始化npm,会写入一个package.json的文件

npm init

第二步:安装 webpack

//当前目录中安装webpack
npm i -D webpack

第二步:安装Webpack-cli

//当前目录中安装
npm i -D webpack-cli

第五步:构建文件

目录结构如下

|-- dist                                      // 项目编译打包目录
|-- src                                       // 项目源文件		
             |-- main.js                       // 程序入口文件,加载各种公共组件
             |--common						  //公共组件文件夹
             		|--scss					  //sass组件
             			main.scss			  //
             		|--js					  //js组件
             			|-- bar.js			  // bar组件
|-- static                                    // 静态文件目录
			 |-- reset.css					  //css文件
|-- webpack.config.js                         // webpack配置文件
|-- index.html                                // 入口html文件
|-- package.json                              // 项目及工具的依赖配置文件
|-- package-lock							  // npm版本控制

inex.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>webpack</title>
</head>
<body>
    <div id="app">
    </div>
    <script src="./dist/bundle.js"></script>
</body>
</html>

reset.css

*{
    margin: 0;
    padding: 0;
}

main.scss

#app div{
    font-size: 40px;
    color: red;
}

bar.js

export function createDiv(str) {
    let div = document.createElement('div');
    div.innerHTML = str;
    return div;
};

export function add(str1,str2) {
    return str1 + str2;
};

main.js

import '../static/css/reset.css';
import './common/js/main.scss';
import { createDiv, add } from './common/js/bar.js';

let sum = add('你好啊, ','webpack');
document.querySelector('#app').appendChild(createDiv(sum));

第六步: 安装css-loader

npm i -D style-loader css-loader

第七步:配置 webpack.config.js

const path = require('path');

module.exports = {
    entry: './src/app.js',
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'bundle.js'
    },
    module: {
        rules: [
          {
            // 用正则去匹配要用该 loader 转换的 CSS 文件
            test: /\.css$/,
            use: [
              'style-loader',
              'css-loader'
            ],
          }
        ]
    }
};

第八步配置 packjson.json

在scripts中加入了下面这一句,这样就可以用 npm run build 来启动目录下的 webpack 了。development 是指输入开发环境的代码,改为production 则为生产环境的代码,即压缩好的。

"build": "webpack --mode development"
{
  "name": "webpack-test",
  "version": "1.0.0",
  "description": "\"第一个webpack测试\"",
  "main": "index.js",
  "scripts": {
    "build": "webpack --mode development",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "dean",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^0.28.10",
    "extract-text-webpack-plugin": "^3.0.2",
    "style-loader": "^0.20.2",
    "webpack": "^4.1.0",
    "webpack-cli": "^2.0.10"
  }
}

第九步:运行webpack,将项目打包

npm run build

然后你就会看到在dist文件夹下生成了 bundle.js,在浏览器中打开index.html就可以看到效果了。

第十步:DevServer 的使用

安装

npm i -D webpack-dev-server

此时 index.html 中的 script:src 要改为bundle.js。因为这个服务器生成的bundle.js是在内存中的

<script src="bundle.js"></script>

然后在 package.json 文件中的scripts中添加

"start": "webpack-dev-server --watch --mode production",

然后启动

npm run start

然后就可以在 localhost:8080 中看到实时预览了。不过这个功能有点坑爹,有时候的效果会不正确。


Loader&&Plugin

前面讲了 webpack 的基本使用,下面再来讲讲常用的 LoaderPlugin

在一般开发中,我们会想让 webpack 帮我们自动处理一些类似于把 es6 转为 es5 这样的事情,这时候就需要使用loaderplugin

经常要用到的 loaderplugin 如下 :

sass

首先全局中安装

npm i -g node-sass

接入webpack

## 安装 webpack loader 依赖
npm i -D sass-loader css-loader style-loader
## sass-loader 依赖 node-sass
npm i -D node-sass

postcss

npm i -D postcss-loader
## postcss支持下一代css
## autoprefixer自动补全前缀
npm i -D postcss-cssnext
npm i -D autoprefixer

这个装完还需要在首目录创建一个文件postcss.config.js

module.exports = {
  plugins: [
    require('autoprefixer')({
       browsers: ['last 10 Chrome versions', 'last 5 Firefox versions', 'Safari >= 6', 'ie > 8']
    }),
    require('postcss-cssnext')
  ]
};

ES6

平常写 es6 的时候都要用babel转为 es5 。webpack 也可以帮你完成。

npm i -D babel-plugin-transform-runtime
# Webpack 接入 Babel 必须依赖的模块
npm i -D babel-core babel-loader 
# 根据你的需求选择不同的 Plugins 或 Presets
npm i -D babel-preset-env

在目录首页创建 .babelrc 文件,内容大致如下,env 表示包含最新版本的所有新特性,更多参数见官方文档

{
  "presets": [
    ["env", { "modules": false }]
  ],
  "plugins": ["transform-runtime"],
  "comments": false
}

url-loader,file-loader

当要在sass里加载图片时,就需要使用 url-loader 和 file-loader。

url-loader是对file-loader的上层封装。设置limit,这样体积小于limit的图片将直接以base64的形式内联在代码中,可以减少一次http请求。

npm i -D url-loader
npm i -D file-loader

配置webpack.config.js

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

extract-text-webpack-plugin

有时我们需要在打包的时候把css文件单独抽离出来,这时候就需要用到 extract-text-webpack-plugin

暂时来说我找不到什么办法可以让 webpack4.1.0 使用这个插件,所以我先把webpack降回到3.1.0版本。

这时 package.json 文件中的 stripts 中的 mode=production 要删去,因为这是webpack4的写法。

npm i -D webpack@3.1.0
npm i -D extract-text-webpack-plugin

然后配置webpack.config.js

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

    module: {
        rules: [
          {
            // 用正则去匹配要用该 loader 转换的 CSS 文件
            test: /\.css$/,
            use: ExtractTextPlugin.extract({
                fallback:'style-loader',
                use:[{'css-loader?minimize&?sourceMap'},'postcss-loader?sourceMap' ]
            }),
          },
        ]
    },
    plugins:[
    	new ExtractTextPlugin('css/main.css')
    ]

这样就可以把css文件在打包的时候单独抽离出来了,再在html文件中link这个文件即可。

minimize 是打包的时候 把css 文件压缩。

sourceMap 是生成转换地图,方便调试。

CleanWebpackPlugin

有时候我们会反复打包多次,在 dist 文件夹下就可能会有多余文件,所以就需要用到这个插件,在每次打包之前先清空 dist 文件夹。或清除指定格式的文件。

npm i -D clean-webpack-plugin

配置如下:

    const CleanWebpackPlugin = require('clean-webpack-plugin');
    plugins:[
        new CleanWebpackPlugin(
            ['dist/*',],  //匹配删除的文件
            {
                root: __dirname,                 //根目录
                verbose:  true,                  //开启在控制台输出信息
                dry:      false                  //启用删除文件
            }
        ),
    ]

webpack.optimize.UglifyJsPlugin

这个插件是webpack自带的,不需要单独安装。


总结

上述所有 loaderplugin 一次性安装。用的 cnpm 是淘宝镜像,装的比较快。这次装的是 webpack@3.1.0

npm init
cnpm i -D webpack@3.1.0 style-loader css-loader sass-loader node-sass postcss-loader postcss-cssnext autoprefixer url-loader file-loader babel-plugin-transform-runtime babel-core babel-loader babel-preset-env extract-text-webpack-plugin webpack-dev-server clean-webpack-plugin

最终的 webpack.config.js 配置如下:

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

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'bundle.js'
    },
    module: {
        rules: [
          {
            // 用正则去匹配要用该 loader 转换的 CSS 文件
            test: /\.css$/,
            use: ExtractTextPlugin.extract({
                fallback:'style-loader',
                use:['css-loader?minimize&?sourceMap','postcss-loader?sourceMap' ]
            }),
          },
          {
            test: /\.scss$/,
            use: ExtractTextPlugin.extract({
                fallback:'style-loader',
                use:['css-loader?minimize&?sourceMap', 'postcss-loader?sourceMap' ,'sass-loader?sourceMap']
            }),
          },
          {
            test: /\.js$/,
            use: ['babel-loader'],
            exclude: [/node_modules/]
          },
          {
              test:/\.(png)|(jpg)|(jpeg)|(gif)$/,
              use: ['url-loader?limit=8192&name=img/[name].[ext]']
          }
        ]
    },
    plugins:[
        new CleanWebpackPlugin(
            ['dist/*',],  //匹配删除的文件
            {
                root: __dirname,                 //根目录
                verbose:  true,                  //开启在控制台输出信息
                dry:      false                  //启用删除文件
            }
        ),
        new ExtractTextPlugin({
            filename:`main.css`,
        }),
        new webpack.optimize.UglifyJsPlugin({
          sourceMap: true,
          compress: {
            warnings: false
          }
        })
    ],
    devtool: 'source-map',
};`

.babelrc

{
  "presets": [
    ["env", { "modules": false }]
  ],
  "plugins": ["transform-runtime"],
  "comments": false
}

postcss.js

module.exports = {
  plugins: [
    require('autoprefixer')({
        browsers: ['last 10 Chrome versions', 'last 5 Firefox versions', 'Safari >= 6', 'ie > 8']
    }),
    require('postcss-cssnext')
  ]
};

这样配置完毕之后,我们就可以使用 ES6/7 + sass 去写项目,最终用 webpack 去打包,压缩,就可以生成兼容的页面了。如果用的是 Vue 或 Rect 则修改 一些参数即可。


下一篇 SASS 用法总结

Comments

Content