webpack 使用-初级篇

134 阅读2分钟

前言

作为前端开发人员,webpack是我们用来打包发布的神兵利器,他的重要性不用我多说了,目前行业内大多数团队构建工具用的应该还是webpack,由此可见一斑。接下来我就说说我们如何利用webpack来构建我们应用。 以下内容基于webpack 4.16.0

webpack的基本使用

1.webpack 安装
npm install webpack webpack-cli --save-dev
2.webpack处理单页面

项目根目录下新建webpack.config.dev.js

const path=require('path');
module.exports={
    entry:{
        index:'./src/index.js' 
    },
    output:{
        filename:'[name].js',
        path: path.resolve(__dirname, "dist"),
    },
    mode:"production" //开发模式下使用development
}
3.package配置

package.json中script里面添加:

"build": "webpack --config ./webpack.config.dev.js"

然后运行 npm run build 即可

4.webpack开发模式-热更新
npm install --save-dev webpack-dev-server
const webpack = require("webpack");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");

module.exports = {
  entry: {
    index:'./src/index.js' 
  },
  output: {
    filename:'[name].js',
     path: path.resolve(__dirname, "dist"),
  },
  mode: "development", // 开发模式
  devtool: "source-map", // 开启调试
  devServer: {
    contentBase: path.join(__dirname, "dist"),
    port: 8000, // 本地服务器端口号
    hot: true, // 热重载
    overlay: true, // 如果代码出错,会在浏览器页面弹出“浮动层”。类似于 vue-cli 等脚手架
    proxy: {
      // 跨域代理转发
      "/api": {
        target: "https://m.weibo.cn",
        changeOrigin: true,
        logLevel: "debug",
        headers: {
          Cookie: ""
        }
      }
    }
  },
  plugins: [
    new HtmlWebpackPlugin({
      filename: "index.html",
      template: "./index.html"
    }),
    new webpack.NamedModulesPlugin(),//当开启 HMR 的时候使用该插件会显示模块的相对路径,建议用于开发环境。
    new webpack.HotModuleReplacementPlugin()
  ]
};

pakage.json 配置

 "dev": "webpack-dev-server --open --config webpack.config.dev.js"

运行npm run dev 即可

5.处理js
npm install babel-loader -D

module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader',
            }
        ]
   }
6.处理css、less、sass

mini-css-extract-plugin 可以帮助我们将css导出到文件上,这样的好处是可以充分使用浏览器缓存。

npm install --save-dev mini-css-extract-plugin
npm install --save-dev css-loader 

如果项目使用less,还需安装less-loader
npm install --save-dev less-loader

如果项目使用sass,还需安装sass-loader
npm install --save-dev sass-loader

const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
  plugins: [
  	//输出css文件
    new MiniCssExtractPlugin({
       chunkFilename: 'assets/styles/[id]-[contenthash:8].css',
       ignorOrder:true
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
         	MiniCssExtractPlugin.loader,
          'css-loader',
        ],
      },
      {
      test: /.less$/,
      use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader'
        ]
      },
      {
      test: /\.scss$/,
      use: [{
          loader:MiniCssExtractPlugin.loader,
      }, {
          loader: "css-loader"
      }, {
          loader: "sass-loader"
      }
    ],
  },
};
7.处理vue文件
npm install -D vue-loader vue-template-compiler

const VueLoaderPlugin = require('vue-loader/lib/plugin')

module.exports = {
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader'
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin()
  ]
}
8.处理图片
npm install -D file-loader url-loader

rules: [
      {
        test: /\.(png|jpg|gif)$/,
        use: [
          {
            loader: 'url-loader',
            options: {
              esModule: false, // 不加的话会有这种情况 img属性src="[object Module]"
              limit: 1024 * 20,
              name: 'assets/images/[name]-[contenthash:8].[ext]'
            }
          }
        ]
      }
    ]
9.处理字体
rules: [
      {
        test: /\.(ttf|woff)$/,
        use: [
          {
            loader: 'file-loader',
            options: {
            	name:'assets/styles/font/[name]-[contenthash:8].[ext]'
            }
          },
          {
            loader: 'url-loader',
            options: {
              limit: 10240
            }
          }
        ]
      }
    ]
10.处理svg

svg在前端中是使用频率非常高的图形资源,为了方便,我们可以通过标签式的方式来使用svg,无需编写什么image/backgroud 等。通过即可使用

npm install -D svg-sprite-loader svgo-loader

icons 下面的 index.js 写入以下内容:

//icons/index.js
import Vue from 'vue'
import SvgIcon from '@/components/SvgIcon'// svg组件
// register globally
Vue.component('svg-icon', SvgIcon)

//引入svg,这里最好是不同模块引入各自的文件夹,避免svg体量过大
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./svg', false, /\.svg$/)
requireAll(req)

入口 main.js 将 index.js 引入:
import '@/icons'
使用:
<svg-icon icon-class="eye"></svg-icon>

webpack 配置:
npm install svg-sprite-loader -D
npm install svgo svgo-loader --save-dev

{
  test: /\.svg$/,
  loader: [{
    	loader:'svg-sprite-loader',
      option: {
        symbolId:"icon-[name]"
      }
  	},
  	{
    	loader:'svgo-loader',
      options: {
              plugins: [
                {removeTitle: true},
                {convertColors: {shorthex: false}},
                {convertPathData: false}
              ]
              }
  	},
  ]
}
11.cleanPlugin

默认会删除output指定的输出⽬目录

plugins:[
	new CleanWebpackPlugin()
]
12.htmlwebpackplugin

BundleAnalyzerPlugin

npm install --save-dev webpack-bundle-analyzer

 plugins: [
    new BundleAnalyzerPlugin()
  ]

结语

总的来说,webpack能在我们做web优化方面提供许多遍历的帮助,这篇文章我们先简单介绍一个入门级的。接下来还会有个进阶篇。同时webpack也在不断地更新中,新版本会不断引入新的特性,使用也越来越简单。让我们拭目以待吧。

最终文件:

  • pakage.json

     "scripts": {
        "dev": "webpack-dev-server --open --config webpack.config.dev.js",
        "build": "webpack --config webpack.config.prod.js"
      },
    
  • webpack.config.dev.js

    const path=require('path');
    const webpack = require("webpack");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    const VueLoaderPlugin = require('vue-loader/lib/plugin');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    module.exports={
        entry:{
            index:'./src/main.js' 
        },
        output:{
            filename:'[name].js',
            path: path.resolve(__dirname, "dist"),
        },
        mode:"development", //开发模式下使用development
        devServer: {
            contentBase: path.join(__dirname, "dist"),
            port: 8000, // 本地服务器端口号
            hot: true, // 热重载
            overlay: true, // 如果代码出错,会在浏览器页面弹出“浮动层”。类似于 vue-cli 等脚手架
            proxy: {
              // 跨域代理转发
              "/api": {
                target: "https://m.weibo.cn",
                changeOrigin: true,
                logLevel: "debug",
                headers: {
                  Cookie: ""
                }
              }
            }
          },
          module:{
            rules:[
                {
                    test: /\.js$/,
                    exclude: /node_modules/,
                    loader: 'babel-loader',
                },
                {
                    test: /\.vue$/,
                    loader: 'vue-loader'
                },
                {
                    test: /\.css$/,
                    use: [
                         MiniCssExtractPlugin.loader,
                      'css-loader',
                    ],
                  },
                  {
                    test: /.less$/,
                    use: [
                        MiniCssExtractPlugin.loader,
                        'css-loader',
                        'less-loader'
                        ]
                  },
                  {
                  test: /\.scss$/,
                  use: [
                        MiniCssExtractPlugin.loader,
                        'css-loader',
                        'sass-loader'
                    ],
                },
                {
                    test: /\.(png|jpg|gif)$/,
                    use: [
                      {
                        loader: 'url-loader',
                        options: {
                          esModule: false, // 不加的话会有这种情况 img属性src="[object Module]"
                          limit: 1024 * 20,
                          name: 'assets/images/[name]-[contenthash:8].[ext]'
                        }
                      }
                    ]
                },
                {
                    test: /\.(ttf|woff)$/,
                    use: [
                      {
                        loader: 'file-loader',
                        options: {
                            name:'./assets/styles/font/[name]-[contenthash:8].[ext]'
                        }
                      },
                      {
                        loader: 'url-loader',
                        options: {
                          limit: 10240
                        }
                      }
                    ]
                }
            ]
          },
          plugins: [
            new HtmlWebpackPlugin({
              filename: "index.html",
              template: "./src/template/index.html"
            }),
            new MiniCssExtractPlugin({
              chunkFilename: 'assets/styles/[id]-[contenthash:8].css',
              ignorOrder:true
            }),
            new CleanWebpackPlugin(),
            new VueLoaderPlugin(),
            new webpack.NamedModulesPlugin(),
            new webpack.HotModuleReplacementPlugin()
          ]
    }
    
  • webpack.config.prod.js

    const path=require('path');
    const webpack = require("webpack");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    const VueLoaderPlugin = require('vue-loader/lib/plugin');
    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    module.exports={
        entry:{
            index:'./src/main.js' 
        },
        output:{
            filename:'[name].js',
            path: path.resolve(__dirname, "dist"),
        },
        mode:"production",
          module:{
            rules:[
                {
                    test: /\.js$/,
                    exclude: /node_modules/,
                    loader: 'babel-loader',
                },
                {
                    test: /\.vue$/,
                    loader: 'vue-loader'
                },
                {
                    test: /\.css$/,
                    use: [
                         MiniCssExtractPlugin.loader,
                      'css-loader',
                    ],
                  },
                  {
                    test: /.less$/,
                    use: [
                        MiniCssExtractPlugin.loader,
                        'css-loader',
                        'less-loader'
                        ]
                  },
                  {
                  test: /\.scss$/,
                  use: [
                        MiniCssExtractPlugin.loader,
                        'css-loader',
                        'sass-loader'
                    ],
                },
                {
                    test: /\.(png|jpg|gif)$/,
                    use: [
                        {
                            loader: 'url-loader',
                            options: {
                              esModule: false, // 不加的话会有这种情况 img属性src="[object Module]"
                              limit: 1024 * 20,
                              name: 'assets/images/[name]-[contenthash:8].[ext]'
                            }
                          }
                    ]
                },
                {
                    test: /\.(ttf|woff)$/,
                    use: [
                      {
                        loader: 'file-loader',
                        options: {
                            name:'./assets/styles/font/[name]-[contenthash:8].[ext]'
                        }
                      },
                      {
                        loader: 'url-loader',
                        options: {
                          limit: 10240
                        }
                      }
                    ]
                }
            ]
          },
          plugins: [
            new HtmlWebpackPlugin({
              filename: "index.html",
              template: "./src/template/index.html"
            }),
            new MiniCssExtractPlugin({
                chunkFilename: 'assets/styles/[id]-[contenthash:8].css',
                ignorOrder:true
            }),
            new CleanWebpackPlugin(),
            new VueLoaderPlugin(),
            new webpack.NamedModulesPlugin(),
            new webpack.HotModuleReplacementPlugin()
          ]
    }