本文正文链接

最近公司弄了个有150+页面的项目,心想,终于有机会可以去学习webpack了,以前想学却没有实际项目去引导逼迫去学,现在终于领略到了webpack的强大了。

什么是webpack

在前端的项目开发中,总有大量的页面和样式需要处理,而维护这些文件也成了头疼的问题。

为了简化开发,于是就有很多好的开发方式,如:

  • 模块化开发。每个功能模块都分开成一个个独立的组件,需要的时候再引入。

  • scss等预处理器。

  • 使用pug, jade 更快编写HTML。

  • ...

这些方式确实可以大大提高开发效率,但是每种方式都有自己的打包方式,还有兼容性处理,如果纯手动处理,必然会增加工作量。

但是,现在有了webpack,上述问题基本解决了,一个webpack就可以处理各种繁琐的过程,给你一个清爽,快速的开发环境。

WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其转换和打包为合适的格式供浏览器使用。

简单的来说,在项目开发中,

  • 你可以使用js,es6/7,甚至ts开发。

  • es6/es7, .ts => .js

  • 使用stylus, scss, less 等预处理器编写css

  • .scss/.less => .css

webpack可以将你项目中的所有文件,处理成浏览器能识别的文件。

开始使用webpack

先新建一个练手用的空文件夹 $ mkdir webpack-demo ,并进入该文件夹。

  1. 新建 package.json.

    $ npm init
  2. 安装webpack及其基本插件。

    $ npm i -D webpack extract-text-webpack-plugin html-webpack-plugin css-loader file-loader style-loader url-loader

    其中:

    • extract-text-webpack-plugin : 该插件主要为了抽离css样式,可以将css从打包的js中抽离出来。以link方式引入样式。

    • html-webpack-plugin : 该插件主要是用于生成html文件,并可以根据入口文件来引入相应的文件。

    • css-loader : 解析css文件中的 importrequire ,并处理他们。

    • style-loader : 将css样式通过 style 标签注入到html文件中。

    • file-loader : 指明webpack将所引入的对象,并返回一个公网能访问的url地址。

    • url-loader : 将文件转换成 base64编码。

  3. 配置webpack。

    新建一个配置文件: $ touch webpack.config.js

    var webpack = require('webpack');
    var path = require('path');var ExtractTextPlugin = require("extract-text-webpack-plugin");
    var HtmlWebpackPlugin = require('html-webpack-plugin');var webpackConfig = {// 设置入口文件。entry: './src/js/index.js',output: {// 设置输出文件夹path: path.join(__dirname, 'dist'),// 设置公用文件夹路径publicPath: '/',// 设置输出的js文件的名字规则。// [name] 为chunk中的名称// [hash] 为webpack生成的哈希值filename: "js/[name].[hash].bundle.js"},module: {rules: [{// 处理css文件test: /\.css$/,loader: "style-loader!css-loader"}, {// 处理html文件,并处理img 中 src 和 data-src 的引入路径test: /\.html$/,loader: "html-loader?attrs=img:src img:data-src"}, {// 处理字体文件test: /\.(woff|woff2|ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,loader: 'file-loader?name=./fonts/[name].[ext]'}, {// 处理图片,并将8k以下的图片转为base64编码test: /\.(png|jpg|gif)$/,loader: 'url-loader?limit=8192&name=./img/[hash].[ext]'}]},plugins: [// 公共js提取new webpack.optimize.CommonsChunkPlugin({name: 'vendors', // 将公共模块提取,生成名为`vendors`的chunk// minChunks: 3 // 提取至少3个模块共有的部分}),// 提取公共css样式new ExtractTextPlugin('./css/[name].css'),// 处理html文件。new HtmlWebpackPlugin({filename: './view/index.html', //生成的html存放路径,相对于pathtemplate: './src/view/index.html', //html模板路径inject: 'body', //js插入的位置,true/'head'/'body'/falsehash: true, //为静态资源生成hash值// chunks: ['vendors', allDirs[i] + '/' + matches[1]], //需要引入的chunk,不配置就会引入所有页面的资源minify: { //压缩HTML文件removeComments: true, //移除HTML中的注释collapseWhitespace: false //删除空白符与换行符}})],// 设置开发服务器devServer: {contentBase: path.join(__dirname, "dist/"),host: 'localhost',port: 9090,inline: true}
    }module.exports = webpackConfig
  4. 测试配置文件:
    先设置开发文件夹目录:

    -   webpack-demo+   node_modules-   src+   js      // 存放js文件+   css     // 存放css样式+   view    // 存放模板文件webpack.config.jspackage.json

    新建一个 html 文件: $ touch ./src/view/index.html

    <!DOCTYPE html>
    <html lang="en">
    <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Hello World</title>
    </head>
    <body><h2>Hello World</h2><p>This is from webpack-demo</p>
    </body>
    </html>

    新建css文件: $ touch ./src/css/index.css

    h2{color: red;opacity: 0.5;transform: rotateZ(-10deg);
    }
    p{color: green;
    }

    新建js文件: $ touch ./src/js/index.js

    // 引入css文件。
    require('../css/index.css')console.log('hello world');

    测试打包: $ webpack
    OK!基本的配置就完成了。

    我们可以看到,在项目中多了一个dist文件夹,里面存放的就是刚刚打包好的文件。打开index.html(需要在服务器中打开,并且服务器根目录为dist)可以看到,生成的html文件,征程显示我们写的内容,css样式则直接写入了style标签当中,而且自动引入了两个js文件,其中,vendors是带有公共部分的js文件,index则是我们一开始写的js逻辑文件。

处理scss文件。

既然都用到了webpack自动打包了,那也顺便使用webpack去处理scss文件(个人爱好是scss,less的处理同理),顺便也处理完css中的其他兼容性问题和浏览器前缀问题吧(程序员的思维就是,懒)。

现在css中需要处理的有:

  1. 浏览器前缀和大部分兼容性问题: autoprefixer

  2. flex 的兼容性问题: postcss-flexibility

  3. opacity 兼容IE: postcss-opacity

  4. 颜色兼容性问题: postcss-color-rgba-fallback

  5. scss文件处理: sass-loader 同时需要依赖 node-sass

  6. 压缩css文件: cssnano

安装上书postcss-loader的插件: $ npm i -D autoprefixer postcss-flexibility postcss-opacity postcss-color-rgba-fallback sass-loader node-sass

现在在webpack中处理css的问题,基本都是通过一个 postcss-loader 去完成所有的处理问题。

先新建一个文件夹,用于存放所有的scss文件: $ mkdir ./src/scss

再新建一个index.scss, $ touch ./src/scss/index.scss

body{background: black;color: white;h2{transform: translateX(10px) rotateZ(-10deg);color: red;opacity: 0.5;}
}

将postcss的加载器中需要的单独提取出来放在一个配置文件中: $ touch postcss.config.js

module.exports = {plugins: [// minify cssrequire('cssnano')({preset: 'default'}),// 处理css前缀require('autoprefixer')({browserslist: ["> 1%","last 2 versions","Edge","ie >= 9"]}),// 处理flex浏览器兼容性require('postcss-flexibility'),// 处理css中rgba颜色代码require('postcss-color-rgba-fallback'),// 处理css中opacity的IE兼容性。require('postcss-opacity')]
}

修改 webpack.config.js:

var webpackConfig = {...module: {rules: [{// 处理css文件test: /\.(scss|sass|css)$/,// loader: "css-loader?importLoaders=1!postcss-loader!sass-loader",// loader执行顺序是从右到左:sass-loader -> postcss-loader -> css-loaderuse: ["style-loader",{loader: "css-loader",options: {// // 0 => no loaders (default); 1 => postcss-loader; 2 => postcss-loader, sass-loaderimportLoaders: 2}},'postcss-loader','sass-loader']},...]}...
}module.exports = webpackConfig

修改一下入口文件中的样式引入: $ vim ./src/js/index.js

require('../scss/index.scss')console.log('hello world');

打包测试:

完美通过。

处理pug/jade文件

项目有很多的页面,而且页面之间也有很多相同的页面,之前写惯了vue的组件,所以注册我们也引入了pug作为前端模板引擎。 pug 的前身就是 jade ,所以语法什么都得基本都是一致的。具体的看 官网 。

和处理css的一样,先要安装加载器。 $ npm i -D pug pug-loader

新建一个简单的页面: $ touch ./src/view/index.pug

htmltitle   Test.html
bodyh2  Welcome to pug.p   This is from index.pug

修改一下配置文件中的html模板入口:

var webpackConfig = {...plugins: [// 公共js提取new webpack.optimize.CommonsChunkPlugin({name: 'vendors', // 将公共模块提取,生成名为`vendors`的chunk}),// 提取公共css样式new ExtractTextPlugin('./css/[name].css'),// 处理html文件。new HtmlWebpackPlugin({filename: './view/index.html', //生成的html存放路径,相对于pathtemplate: './src/view/index.pug', //html模板路径inject: 'body', //js插入的位置,true/'head'/'body'/falsehash: true, //为静态资源生成hash值chunks: ['vendors', 'index'], //需要引入的chunk,不配置就会引入所有页面的资源minify: { //压缩HTML文件removeComments: true, //移除HTML中的注释collapseWhitespace: false //删除空白符与换行符}})],...
}module.exports = webpackConfig

重新编译打包:

使用 babel 来“编译”你的js

在项目开发中,难免会遇到使用 es6 ,甚至 es7 去编写js。但是大部分浏览器却不支持这些语法,这时候,就需要 babel-loader 来处理js,并将其转换为浏览器能识别的 es5 语法。

还是要安装依赖: $ npm i -D babel-loader babel-core babel-preset-es2015

如果用上了es7 的语法,就要根据不同阶段语法提案的转码规则(共有4个阶段),选装一个:

$ npm i -D babel-preset-stage-0
$ npm i -D babel-preset-stage-1
$ npm i -D babel-preset-stage-2
$ npm i -D babel-preset-stage-3

新建一个 .babelrc babel配置文件: $ touch .babelrc

{"presets": ["es2015"],"plugins": []
}

修改 webpack 配置文件:

var webpackConfig = {...module: {rules: [{test: /\.js$/,// 不编译 node_modules 下的文件exclude: /node_modules/,loader: "babel-loader"}]}...
}module.exports = webpackConfig

在 index.js 中写个 es6 的语法:

require('../scss/index.scss')console.log('hello world');((message) => {console.log(message);
})('message from es6')let step = 2;
var add = number => number*=stepconsole.log(add(2));

来,打包看看:


完美。

配置多文件入口

项目有多个页面,每个页面都对应着一个js入口和一个页面,但是,入口 entry 和 html-webpack-plugin 每次只能配置一个具体的入口文件,如果每增加一个页面就要去配置,那么这无形之中增加了工作量,因此,我们需要一个通用的入口文件。

既然在node中可以访问文件夹并读取其中的文件名,那么我们可以使用node来去循环读取文件夹下的js文件,并自动添加至入口配置中:

新建一个config 文件夹,以存放webpack可变的配置,方便以后修改: $ mkdir config

因为遍历入口文件都是一样的操作流程,所以先写一个工具包:$ touch config/utils.js

var fs = require('fs');
// 递归遍历文件夹,获取入口文件
function getAllFiles(dirRoot, type){var filterReg = new RegExp('.'+type+'$');function getAllFileFromDir(root) {var res = [], files = fs.readdirSync(root)files.forEach((file) => {var pathname = root+'/'+file,state = fs.lstatSync(pathname)if (!state.isDirectory()) {// 过滤相对应的文件filterReg.test(pathname) && res.push(pathname)// res.push(pathname.replace(dir_root+'/', ''))}else{res = res.concat(getAllFileFromDir(pathname))}})return res}return getAllFileFromDir(dirRoot)
}function getEntry(files, replaces){var entry = {}for (var i = 0; i < files.length; i++) {var filename = files[i]replaces.map((replace) => {filename = filename.replace(replace, '')})entry[filename] = files[i]}return entry
}module.exports = {getAllFiles,getEntry
}

再新建一个 js 入口文件配置: $ touch config/webpack.entry.js

var path = require('path');
var utils = require('./utils.js')
var dir_root = path.resolve(__dirname, '../src/js');// console.log(getAllFiles(dir_root));
var allFiles = utils.getAllFiles(dir_root, 'js')
var entry = utils.getEntry(allFiles, ['js', dir_root+'/'])
console.log(entry);
module.exports = entry

同样的,页面入口文件也添加一个: $ touch config/webpack.plugins.js

var webpack = require('webpack')
var path = require('path');
var utils = require('./utils.js')var ExtractTextPlugin = require("extract-text-webpack-plugin");
var HtmlWebpackPlugin = require('html-webpack-plugin');var entry = require('./webpack.entry.js')var plugins = [// 公共js提取new webpack.optimize.CommonsChunkPlugin({name: 'vendors', // 将公共模块提取,生成名为`vendors`的chunkminChunks: 3 // 提取至少3个模块共有的部分}),// 提取公共css样式new ExtractTextPlugin('./css/[name].css'),
]
let dir_root = path.resolve(__dirname, '../src/view');
var pugFiles = utils.getAllFiles(dir_root, 'pug')pugFiles = utils.getEntry(pugFiles, ['.pug', dir_root+'/'])for (var key in pugFiles) {if (pugFiles.hasOwnProperty(key)) {let opt = {filename: './view/'+ key +'.html',template: pugFiles[key],hash: true,minify: { //压缩HTML文件removeComments: true, //移除HTML中的注释collapseWhitespace: false //删除空白符与换行符}}if (entry.hasOwnProperty(key)) {opt['chunks'] = ['vendors', key]opt['inject']= 'body'}console.log(opt);plugins.push(new HtmlWebpackPlugin(opt))}
}module.exports = plugins

再次修改webpack的配置:

var entry = require('./config/webpack.entry.js')
var plugins = require('./config/webpack.plugins.js')var webpackConfig = {entry,plugins,...
}module.exports = webpackConfig



可以看到,dist文件夹下,多了几个html文件和js文件。

其他处理

  • 提取css到外部link,而非style标签
    这个解决办法比较简单,只需要用 extract-text-webpack-plugin 插件将css提取出来即可:

    {test: /\.(scss|sass|css)$/,use: ExtractTextPlugin.extract({fallback: "style-loader",use: [{loader: "css-loader",options: {// // 0 => no loaders (default); 1 => postcss-loader; 2 => postcss-loader, sass-loaderimportLoaders: 2}},'postcss-loader','sass-loader']})
    }

    再次打包的结果:

    列出dis文件夹的目录树可以发现,多了一个css的文件夹。打开页面可以发现,页面中的style标签已经被link替代了。

  • 每次打包旧的文件依旧存在
    每次执行webpack打包(当然在实际开发中应该使用热更新服务器,不需要频繁打包)都会产生一堆新的js文件。

    解决办法:

    一是将打包的js文件的hash值去掉,这样就会新的打包js文件,将旧的覆盖。

    二是使用 clean-webpack-plugin

    var CleanWebpackPlugin = require('clean-webpack-plugin');
    var plugins = [// 每次打包前都清空dist文件new CleanWebpackPlugin(['dist'], {root: path.resolve(__dirname, '../')}),// 公共js提取new webpack.optimize.CommonsChunkPlugin({name: 'vendors', // 将公共模块提取,生成名为`vendors`的chunk// minChunks: 3 // 提取至少3个模块共有的部分}),// 提取公共css样式new ExtractTextPlugin('./css/[name].css'),
    ]
  • 批量新建文件
    因为每个页面基本都有3个文件:page.pug, page.js, page.scss,如果每次新加一个页面都要手动新建3个文件的话,效率太低下,能用命令行解决的,当然要用命令行解决啦。

    先写个小脚本 newpage.sh:

    #!/bin/sh
    if [[ $1 ]]; thenfilename=$1touch ./src/js/$filename.jstouch ./src/view/$filename.pugtouch ./src/scss/$filename.scss
    fi

    使用方式就是: $ ./newpage.sh filename,要运行该脚本,就需要先将脚本设置为可执行: $ sudo chmod +x ./newpage.sh

    还可以将它写进 npm 的 package.json 的命令中,则命令可以变为:npm run new -- filename

    {"script": {"new": "./newpage.sh"}
    }
  • 定义路径常量
    在编写js时,因为有可能js文件是在很多级的目录当中,如果每次都使用 .. 来定位上一层目录的话,那么这个定位就会十分繁琐。这时可以使用 webpack 提供的 resolve.alias 配置来使引入文件的时候变得更加方便简单。

    resolve: {alias: {scss: path.resolve(__dirname, 'src/scss'),js: path.resolve(__dirname, 'src/js'),view: path.resolve(__dirname, 'src/view'),assets: path.resolve(__dirname, 'src/assets')}
    }

    这样,在 other.js 中,就可以直接使用 require('scss/about.scss') 而不需要写繁琐的 require('../../scss/about.scss')。这样就方便多了。

webpack 简易配置入门教程相关推荐

  1. webpack 教科书式入门教程

    最近刚用完gulp又来捣鼓捣鼓webpack,这只是个简单的新手入门教程...不多说: 注意:安装webpack前检查nodejs的安装目录路径是否存在空格(Program Files (x86)), ...

  2. nginx rails 详细站点配置入门教程

    Ruby on Rails 是一个用于开发数据库驱动的网络应用程序的完整框架.Rails基于MVC(模型- 视图- 控制器)设计模式.从视图中的Ajax应用,到控制器中的访问请求和反馈,到封装数据库的 ...

  3. c# 定位内存快速增长_CTF丨Linux Pwn入门教程:针对函数重定位流程的相关测试(下)...

    Linux Pwn入门教程系列分享已到尾声,本套课程是作者依据i春秋Pwn入门课程中的技术分类,并结合近几年赛事中出现的题目和文章整理出一份相对完整的Linux Pwn教程. 教程仅针对i386/am ...

  4. webpack简易入门

    webpack简易学习教程 1.为什么要用webpack? 模块化开发 代码压缩,合并,提取公共代码, 编译ES6,CoffeeScript: Scss,Less等css预处理器 2.webpack简 ...

  5. webpack轻松入门教程

    webpack之傻瓜式教程及前端自动化入门 接触webpack也有挺长一段时间了,公司的项目也是一直用着webpack在打包处理,但前几天在教新人的情况下,遇到了一个问题,那就是:尽管网上的webpa ...

  6. webpack快速入门教程

    webpack快速入门教程 1.webpack 介绍 什么是webpackhttps://www.webpackjs.com/ Webpack是一个模块打包器(bundler) 在Webpack看来, ...

  7. 简易的服务器接口开发入门教程

    前沿 谷丝小说网 https://www.wayi.info 为了解决服务器接口开发的问题,因此学习了关于Spring Boot的知识,然后再自己摸索总结后台的开发经验.所以这篇文章就是面向搞移动开发 ...

  8. 【Gazebo入门教程】第五讲 控制器插件的编写与配置(上)

    [Gazebo入门教程]第五讲 控制器插件的编写与配置(上) 文章目录 [Gazebo入门教程]第五讲 控制器插件的编写与配置(上) 一.控制插件的使用方法 1. 插件简介 2. 插件编写流程 二.模 ...

  9. Webpack 入门教程

    Webpack 是一个前端资源加载/打包工具.它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源. 本章节基于 Webpack3.0 测试通过. 从图中我们可以看出,W ...

最新文章

  1. 23 个优秀的机器学习训练公共数据集
  2. build.xml java打包_配置pom.xml用maven打包java工程的方法(推荐)
  3. Flutter 以Dialog Activity形式展现
  4. SpringBoot中Mybatis打印sql日志
  5. Java 动态代理实现
  6. 浅谈Spring测试框架+junit4单元测试原理
  7. Spark的三种运行模式
  8. 设置SUID用于提权或降权
  9. Git Commit failed with error The Git process exited with the code -1,073,741,819
  10. 聚焦应对最新网络安全挑战,2022 BLACK HAT- OMDIA分析师大会报告开放申请
  11. SSRS报表服务随笔(rdl报表服务)-报表结构与样式
  12. openbmc开发30:webui开发—基础
  13. project之任务计划(任务之间的依赖关系)
  14. Java8 装逼for循环写法
  15. 马云控股“文化中国”暗藏啥玄机?
  16. 苹果开发者账号续费时出现你的支付授权失败,请核对信息并重试..
  17. 兔子--sdk版本与api的对应关系
  18. 转载老码农教你学英语
  19. 小八,Hachiko——我心中的英雄
  20. 【JokerのLabView】程序结构。

热门文章

  1. linux ---硬盘的挂载
  2. 安装Ubuntu20.04双系统
  3. three.js方向光DirectionalLight使用,调整方向光颜色、光源位置、光照强度、光照指向、是否可见、是否产生阴影属性(vue中使用three.js10)
  4. 迭代算法1——精确迭代法之最大公约数与最小公倍数
  5. Windows beanstalkd启动
  6. 使用Python爬取上交所问询函并查询相关股票发函日股价
  7. 已 树莓派4b ros 系统 网盘_无限可能:树莓派4B 安装Ubuntu18.04+ROS1(melodic)
  8. HTTPConnectionPool(host=‘127.0.0.1‘, port=44245) 解决方案
  9. 简单分享怎么通过微信小程序开店
  10. AutoSAR系列讲解(入门篇)5.4-ECU的项目流程