Webpack 本地搭建

Posted by violetks on September 1, 2020

webpack是一个模块打包工具。参考《深入浅出 Webpack》

Webpack 的本地搭建

1、新建文件夹 webpack-demo。

// index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app"></div>
  <script src="./src/index.js"></script>
</body>
</html>
// src/index.js
import Header from './header.js';
import Content from './content.js';

new Header();
new Content();
// src/header.js
function Header() {
  var dom = document.getElementById('app');
  var header = document.createElement('div');
  header.innerText = 'header';
  dom.append(header);
}

export default Header;
// src/content.js
function Content() {
  var dom = document.getElementById('app');
  var content = document.createElement('div');
  content.innerText = 'content';
  dom.append(content);
}

export default Content;

2、npm init [-y]初始化项目,生成 package.json 文件。

3、安装 webpack 和 webpack-cli。

上面代码中import语句是使用ES6语法,浏览器不能识别,需要通过webpack转换后才能正常运行。

# 在项目里安装因为可能不同项目中使用不同 webpack 版本
$ npm i webpack webpack-cli -D

$ webpack -v             // 打印出全局的版本
$ npx webpack -v         // 打印出当前目录的版本

$ npm info webpack       // 安装前查看版本号
$ npm install webpack@4.16.5 webpack-cli -D  // 安装指定版本

4、修改 package.json 文件。

加上"private": true表示私有,设置为true时,npm拒绝发布。
"main": "index.js"可以去掉。
"dev": "webpack"修改打包命令,之前是npx webpack打包,现在是npm run dev打包。

aTVWg1.png

5、项目根目录下新建webpack的配置文件webpack.config.js

// webpack.config.js
const path = require('path');

module.exports = {
  mode: 'production',// 默认值为 production
  // JavaScript 执行入口文件
  entry: './src/index.js',
  output: {
    // 将所有依赖的模块合并输出到一个 bundle.js 文件
    filename: 'bundle.js',
    // 将输出文件都放到 dist 目录下
    path: path.resolve(__dirname, './dist'),
  }
};
# 设置 webpackconfig.js 为配置文件
$ npx webpack --config webpackconfig.js

6、npx webpack/npm run dev打包,生成dist文件夹,里面有bundle.js文件。

aTKR8e.png

7、在index.html将打包文件引入,再打开index.html,页面运行成功。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app"></div>
  <!-- 导入 Webpack 输出的 JavaScript 文件 -->
  <script src="./dist/bundle.js"></script>
</body>
</html>

Loader

webpack除了 JavaScript,还可以通过loader引入任何其他类型的文件,例如 CSS、图片等。
如果一个源文件需要多步转换,就通过多个 Loader 链式顺序执行实现,执行顺序从右到左。

1、打包图片,先安装 loader,然后再配置打包规则

npm install url-loader -D
// webpack.config.js
const path = require('path');

module.exports = {
  mode: 'development',// 默认值为 production
  // JavaScript 执行入口文件
  entry: {
    main: './src/index.js'
  },
  module: {
    rules: [
      // 配置打包图片 loader 规则
      {
        test: /\.(jpg|png|gif)$/,
        use: {
          loader: 'url-loader',
          options: {
            name: '[name].[ext]',  // 打包后图片命名规则
            outputPath: 'images/', // 输出路径
            limit: 204800,  // 小于 200KB 用 url-loader 打包,大于用 file-loader 打包
          }
        }
      }
    ]
  },
  output: {
    // 将所有依赖的模块合并输出到一个 bundle.js 文件
    filename: 'bundle.js',
    // 将输出文件都放到 dist 目录下
    path: path.resolve(__dirname, './dist'),
  }
};

使用url-loader打包图片,它会将图片转换为base64字符串加入bundle.js中,而不是单独生成一个图片文件,适用于较小的图片打包,减少额外的 HTTP 请求。较大的图片使用file-loader打包到dist目录下,减少加载时间。

2、打包静态资源,如 CSS 样式文件

npm install style-loader css-loader -D
npm install sass-loader node-sass -D
npm install postcss-loader -D
npm install autoprefixer -D
// webpack.config.js 相关代码片段
module: {
  rules: [
    {
      test: /\.(css|scss)$/,
      use: [
        'style-loader',
        // 'css-loader',
        {
          loader: 'css-loader',
          options: {
            importLoaders: 2, // 在 css-loader 前应用的 loader 的数量,确保每个样式文件能通过所有 loader 编译
            modules: true, // 开启 CSS 模块化打包
          }
        },
        'sass-loader',
        'postcss-loader', // 可为 transform 等样式自动添加厂商前缀
      ], // 执行顺序从右到左
    }
  ]
}

postcss-loader可为 transform 等样式自动添加厂商前缀,使用前需要新建一个postcss.config.js文件。

// postcss.config.js
module.exports = {
  plugins: [
    require('autoprefixer')
  ]
};

// postcss.config.js 在工作项目中的写法
module.exports = {
  plugins: {
    autoprefixer: {}
  }
};

142904.png

3、打包字体图标文件

npm install file-loader -D
// webpack.config.js 相关代码片段
module: {
  rules: [
    {
      test: /\.(eot|ttf|svg)$/,
      use: {
        loader: 'file-loader',
      }
    }
  ]
}

Plugin

loader用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。包括:打包优化,资源管理,注入环境变量。

1、使用html-webpack-plugin打包时自动生成 HTML 文件。

html-webpack-plugin会在打包结束后,自动生成一个 HTML 文件,并把打包生成的 JS 自动引入到这个 HTML 文件中。

// webpack.config.js 相关代码片段
plugins: [
  new HtmlWebpackPlugin({
    template: 'src/index.html', // 以 src 下的这个文件为模板生成
  }),
],

2、clean-webpack-plugin在打包之前,删除 dist 目录下所有文件。

3、通过Plugin将注入bundle.js文件里的 CSS 提取到单独的文件中。

npm i -D extract-text-webpack-plugin
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
  mode: 'development',
  devtool: 'source-map',
  // JavaScript 执行入口文件
  entry: {
    main: './src/index.js'
  },
  output: {
    // 将所有依赖的模块合并输出到一个 bundle.js 文件
    filename: 'bundle.js',
    // 将输出文件都放到 dist 目录下
    path: path.resolve(__dirname, './dist'),
  },
  module: {
    rules: [
      // 配置打包 CSS 的 loader 规则
      {
        // 用正则去匹配要用该 loader 转换的CSS文件
        test: /\.css$/,
        loaders: ExtractTextPlugin.extract({
          // 转换 .css 文件需要使用的 Loader
          use: ['css-loader'],
        })
      }
    ]
  },
  plugins: [
    new ExtractTextPlugin({
      // 从 .js 文件中提取出来的 .css 文件的名称
      filename: `[name]_[contenthash:8].css`,
    }),
  ]
};