webpack2 基础入门详解

本文详细介绍了webpack2的基础入门,包括前提条件、安装步骤、配置文件详解,以及如何处理JS、CSS、SASS文件,使用webpack-dev-server搭建开发服务器,分离公共代码,使用CSS Module和自动引入JS输出文件。通过实例展示了如何将多个JS输入文件打包为多个输出文件,并讲解了在CSS3属性中添加私有前缀的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

看过许多关于webpack的文章,最近终于有时间(实习+学校课程设计)去解决之前mac终端npm command not found的问题,再去使用webpack工具啦~

这里写图片描述


前提

  1. 使用webpack的前提条件:我的电脑是mac,先下载node-XXX.pkg。在下载完成之后,我输入node -v,并没有显示版本号,而是node command not found。很多时候我都是卡在mac的文件夹权限问题上,或是PATH配置问题。
  2. 如果你也出现这样的问题,因为node是默认安装在/use/local/bin下,export PATH=$PATH:/usr/local/bin来配置PATH。这时候命令不存在的问题就解决啦~


安装

接下来我们就开始一步一步的安装使用webpack。(以下以mac为例)

  1. 打开”终端”
  2. 创建一个文件夹mkdir mydirectory(默认在padonis下,如需修改路径可以cd进入其它目录)
  3. 进入该文件夹cd my directory
  4. npm init
  5. 指定webpack版本号 npm install webpack@2.2.1 --save -dev

注:这里nam install webpack –save -dev默认下载最新版本,我默认下载的是webpack3.0.0,可以通过npm install webpack@2.2.1 --save-dev指定版本号,推荐1.x版本或2.x版本,很多webpack技术文章都是这些旧版本,而且我在用3.0.0版本的时候独立出css插件部分使用有点问题

这里写图片描述

如果在你cd的目录里看到node_modules文件夹就说明安装webpack成功了。(根目录下会出现一个node_modules文件夹,npm安装的各种依赖包都会默认安装到这个文件夹下面)

并且多了一个package.json文件,内容就是一堆json数据,基本就是我们刚才在终端里输入的信息

这里你会看到mydirectory文件夹下还有app文件夹、public文件夹和webpack.config.js文件,这些都是需要我们自己创建的(当然文件夹名字你可以自定义)。

app文件夹(自定义):放置我们的开发文件

public文件夹(自定义):就是浏览器执行需要的文件

webpack.config.js文件(自定义 必须):webpack的配置文件,稍后会详细说明


简单入门

在app文件夹下创建一个main.js文件

//main.js
document.write("hello world!");

在app文件夹下创建一个main.js文件

//basic.js
document.write('HELLO,Suoz!');

在app文件夹下创建一个index.html文件

//index.html
<div id="box">
    <h2>h1</h2>
    <p>webpack</p>
</div>

<script type="text/javascript" src="../public/app.bundle.js"></script>

接下来在webpack.config.js文件下修改配置,这里entry代表指定的入口文件(这个入口文件可以通过require引入其它文件),output代表输出文件(即将所有入口文件指定的资源按照依赖关系打包输出一个输出文件,并放到index.html中引入即可)

//在webpack 2.2.1版本下配置
const webpack = require("webpack");

module.exports = {
  context: __dirname,
  entry: {
    app: ["./app/main.js"],
  },
  output: {
    path: __dirname + "/public",
    filename: "[name].bundle.js",
  },
};

__dirname : 根目录(这里的根目录是mydirectory文件夹)

Webpack 基本做了下面这些事情:

  1. 从 context 对应的文件夹开始…
  2. …寻找 entry 里所有的文件名…
  3. …然后读取它们的内容。在解析代码时,每一个通过 import(ES6) 或 require() (Node) 引入的依赖都会被打包到最终的构建结果当中。它会接着搜索 那些依赖,以及那些依赖的依赖,直到“依赖树”的叶子节点 — 只打包它所需要的依赖,没有其他的东西。
  4. 接着,Webpack 将所有东西打包到output.path 对应的文件夹里,使用 output.filename 对应的命名模板来命名( [name] 被 entry里的对象键值所替代)

关于webpack的启动方式:

webpack // 最基本的启动webpack的方法

webpack -w // 提供watch方法;实时进行打包更新

webpack -p // 对打包后的文件进行压缩

webpack -d // 提供source map,方便调式代码

注:webpack3.0.0版本下的输出文件path不能直接是’./public’,否则会出现configuration.output.path: The provided value "./public" is not an absolute path!的错误

这里写图片描述

此刻的mydirectory文件夹目录:
这里写图片描述

输出文件名为bundle.js,由于在./app/index.html中引入了bundle.js,所以打开index.html时,页面如下图:
这里写图片描述


多个JS输入文件 多个输出JS文件

const webpack = require("webpack");

module.exports = {
  context: __dirname,
  entry: {
    home: ["./home_1.js","./home_2.js"],
    events: ["./events.js"],
  },
  output: {
    path: __dirname + "/public",
    filename: "[name].bundle.js",
  },
};

=>home_1.js和home_2.js文件 输出一个home.bundle.js文件
=>events.js文件 输出一个events.bundle.js文件


CSS文件 css-loader style-loader

你可能注意到甚至在生产构建的结果中,也把 CSS 打包进了 JavaScript 里面,并且 style-loader 手动地将样式写进了 <-head> 中。乍一看这可能有点奇怪,但当你考虑足够多的时候就会慢慢发现这其实是有道理的。你保存了一个头部请求(在某些连接上节省宝贵的时间),并且如果你用 JavaScript 来加载 DOM(通过DOM操作动态创建<-style>,并通过代码将样式添加在<-style>标签中),这么做基本上就消除了它自身的无样式闪屏问题。

前提:需要使用npm命令下载style-loader和css-loader。因为webpack只能识别原生的js模块,而对于css模块、ES6模块等都需要通过loader加载器进行转换,转换成webpack能识别的模块。

//在终端输入
npm install style-loader --save-dev
npm install css-loader --save-dev

下载完成之后,在package.json文件下你会发现自动多了这么一行即代表下载成功

"dependencies": {
    "css-loader": "^0.28.4",
    "style-loader": "^0.18.2"
  }

接下来开始创建相关的文件 并 写入代码

//basic.css
body{
    font-size: 40px;
    color: red;
}
//main.js
document.write("hello,main.js");
require("./basic.css");
const webpack = require("webpack");

module.exports = {
  //...code
  module: {
    rules: [
        {
            test: /\.css$/,
            use: ["style-loader","css-loader"],
            //这些 loader 会以数组逆序运行。这意味着 css-loader 会在 style-loader 之前运行
        },
    ],
  },
};
//index.html不变,还是引入app.bundle.js文件

<div id="box">
    <h1>hello</h1>
    <p>webpack</p>
</div>
<script type="text/javascript" src="../public/app.bundle.js"></script>

这里写图片描述

总结:把CSS文件放入JS文件中一起打包出一个输出文件,同时在.html也只是引用这个js文件,但是这个文件内部会自动帮我们动态创建一个<-style>标签,并将CSS中的样式通过DOM操作加入<-style>标签内部,无需我们操心。这样也减少了请求文件(JS、CSS)的数量。

注:先执行css-loader将css样式转换为webpack能够识别的模块,再通过style-loader将模块通过JS DOM操作动态创建<-style>标签,并加入<-head>标签内部。因此在后面独立出CSS文件中无需在加入style-loader


index.html显示如图:
这里写图片描述

SASS sass-loader

安装sass-loader加载器:
npm install sass-loader --save-dev

//basic.scss
body{
    font-size: 40px;
    & p{
        font-size: 20px;
        color: #ccc;
    }
}
//basic.css
#box{
    width: 400px;
    height: 400px;
    background-color: green;
}
//main.js
document.write("hello,main.js");
require("./basic.scss");
require("./basic.css");
//index.html

<div id="box">
    <h1>hello</h1>
    <p>webpack</p>
</div>
<script type="text/javascript" src="../public/app.bundle.js">
//然后添加另外一条rules
module.exports = {
  // …
  module: {
    rules: [

      {
        test: /\.(sass|scss|css)$/,
        use: [
          "style-loader",
          "css-loader",
          "sass-loader",
        ]
      },

      // other ...

    ],
  },
};

这里写图片描述

一片片的红海啊。。有点刺眼,我们看看发生了什么,原来是提示没有安装node-sass模块,那么我们继续安装:

npm install node-sass --save-dev

再次执行 webpack -w,就成功啦~

这里写图片描述


独立出CSS文件

遇到一个bug,在webpack2.X版本下,extract-text-webpack-plugin最好也使用2.X版本。如果不指定版本,可能会导致错误。

这里写图片描述

npm install extract-text-webpack-plugin@2.0.0-beta.4 --save-dev

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


    context: __dirname,

    entry: {
        app: ["./app/main.js"],

    output: {
        path: __dirname + "/public",
        filename: "[name].bundle.js",
    },

  module: {
    rules: [
      {
        test: /\.css$/,
        loader:  ExtractTextPlugin.extract({
          //注:这里没有style-loader
          loader: 'css-loader?importLoaders=1',
        }),
      },
      // …
    ]
  },

    plugins: [
        new ExtractTextPlugin({
          filename: "[name].bundle.css",
          allChunks: true,
        }),
    ],
};

而webpack2.2文档是这么定义的,但是使用npm命令下载的插件默认是3.x版本,而且按照官网的也不能实现,如果有大牛知道请告诉我。
这里写图片描述


SASS+独立出CSS

一开始[“style-loader”,”css-loader”,”sass-loader”]。后来才知道style-loader是为了将样式动态加入head标签内部。在这里再次提醒~~独立出CSS文件千万不要有style-loader

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

module: {
    rules: [
        {
            test: /\.(sass|scss|css)$/,
            loader:  ExtractTextPlugin.extract({
                loader: 'css-loader!sass-loader?importLoaders=1',
            }),
        },
    // …
    ]
},

plugins: [
    new ExtractTextPlugin({
      filename: "[name].bundle.css",
      allChunks: true,
    }),
],


ECMAScript6转换器babel

都知道ES6代码在大部分浏览器下不能直接运行。所以需要通过babel转换器转换为ES5代码。而webpack提供了这个功能。

npm install babel-loader babel-core babel-preset-es2015

// ...code
 module: {
   rules: [
     {
       test: /\.js$/,
       use: [{
         loader: "babel-loader",
         options: { presets: ["es2015"] }
       }],
     },
     // Loaders for other file types can go here
   ],
 },
//basic.js(es6代码)
let arr = [1,2];
let [a,b] = arr;

document.write(a + ":" + b);
//入口文件main.js
require("./basic.js");

这里写图片描述


开发服务器 webpack-dev-server

实际上 Webpack 有它自己的开发服务器,所以无论你正在开发一个静态网站,或者只是正在原型化前端阶段,这个服务器都是完美可用的。想要运行它,只需要在 webpack.config.js 里添加一个 devServer 对象:

module.exports = {
  context: __dirname + "/app",
  entry: {
    app: "./main.js",
  },
  output: {
    filename: "[name].bundle.js",
    path: __dirname + "/public/assets",
    publicPath: "/assets",            // New
  },
  devServer: {
    contentBase: __dirname + "/app",  // New
  },
};

现在新建一个 app/index.html 文件,加入下面这行:

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

然后在命令行中,运行:

webpack-dev-server

服务器现在就运行在了 localhost:8080 上。注意 script 标签中的 /assets 对应的是 output.publicPath 的值 - 可以随便填成你想要的命名(如果需要一个 CDN,这就很有用了)。

当你更改 JavaScript 代码的时候,Webpack 就会实时更新页面而无需手动刷新浏览器。但是, 任何对 webpack.config.js 的更改都需要重启服务器 才可以生效。


分离出公共代码

如果你正在将应用拆解,打包成多个 output 的话(如果应用的某部分有大量不需要提前加载的 JS 的话,这样做会很有用),那么在这些文件里就有可能出现重复的代码,因为在解决依赖问题的时候它们是互相不干预的。幸好,Webpack 有一个内建插件 CommonsChunk 来处理这个问题:

const CommonsChunkPlugin = require("webpack/lib/optimize/CommonsChunkPlugin");

plugins: [
    new webpack.optimize.CommonsChunkPlugin({
        name: "commons",
        filename: "commons.js",
        minChunks: 2,
    }),
],


CSS Module 作用域

都知道CSS是全局定义的,如果一个开发者定义一个类.style,并为它设置样式。另一个开发者定义同一个类.style。此时的后面定义中同名属性会覆盖前面的。如果想解决这个问题,可以使用webpack中css-loader设置属性。

//basic.css
body{
    background-color: blue;
}

.class1{
    color: green;
}
//basic_2.css
body{
    background-color: white;
}

.class1{
    color:  pink;
}
//component.js
export default(class1,class2) => {
    var box = document.getElementById("box");
    box.className = class1;

    var p = document.getElementById("p");
    p.className = class2;

    return;
}
//main.js

import component from "./component.js";
import basic1 from "./basic.css";
import basic2 from "./basic_2.css";

component(basic1.class1,basic2.class1);
//webpack.config.js
module: {
    rules: [
        {
            test: /\.css$/,
            use: ['style-loader',{
                loader: 'css-loader',
                //为css-loader设置属性
                options: {
                    modules: true,
                },
            }],
        },
    ]
},


自动引入JS输出文件

通过webpack.config.js中output输出的文件,每次你都要在.html文件内部引入,如果你觉得麻烦,在webpack内部提供了html-webpack-plugin插件为你自动引入。

const webpack = require("webpack");
var HtmlWebpackPlugin = require('html-webpack-plugin');


module.exports = {
    context: __dirname+"/app",
    entry: {
        app: ["./main.js"],
        demo : ["./demo.js"],
    },
    output: {
        path: __dirname + "/public",
        filename: "[name].bundle.js",
    },

    plugins: [
        new HtmlWebpackPlugin({
            title: '首页',
            template:__dirname+'/app/index.html', // 文件模板
            filename: __dirname + '/public/index.html', // 生成的文件名
            chunks:["app"], //引入的JS模块
        }),
        new HtmlWebpackPlugin({
            title: '购物车',
            template:__dirname+'/app/index.html', // 文件模板
            filename: __dirname + '/public/basic.html', // 生成的文件名
            chunks:["demo","app"], //引入的JS模块
            //chunks 选项的作用主要是针对多入口(entry)文件。当你有多个入口文件的时候,对应就会生成多个编译后的 js 文件。那么 chunks 选项就可以决定是否都使用这些生成的 js 文件。chunks 默认会在生成的 html 文件中引用所有的 js 文件,当然你也可以指定引入哪些特定的 js 文件。
        }),
    ]
};

这里写图片描述

到这儿你会发现public目录下的index.html和basic.html都引用了app目录下的index.html。而前者在body结束标签前面引入了app.bundle.js输出文件,后者不仅引入了demo.bundle.js,还引入了app.bundle.js。


./app/index.html
这里写图片描述

./publuc/index.html
这里写图片描述

./public/basic.html
这里写图片描述


CSS3属性添加私有前缀 postcss-loader

nam install postcss-loader --save -dev
module: {
    rules: [
        {
            test: /\.css$/,
            use: ['style-loader',
                {
                    loader: 'css-loader',
                    options: {
                        modules: true,
                    },
                },
                {
                    loader: "postcss-loader", // 添加浏览器前缀
                    options: {
                        plugins: function () {
                            return [
                                require('autoprefixer')
                            ]
                        }
                    }
                },
            ],
        },
    ]
},
body{
    display: flex;
}

.class1{
    color: green;
}

=>
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值