webpack入门

前端工程化:自动化(用命令行自动转译)、模块化、性能优化
模块自动化构建工具:webpack的使用
postcss:自动添加浏览器私有前缀
sass:sass转css
less:less转css
babel:es6转es5
extract-text-webpack-plugin:分离出独立的css文件
webpack4参考教材
webpack:从入门到真实项目配置
关于 webpack 的面试题有哪些?
简书:webpack4入门

前端工程化

大公司里怎样开发和部署前端代码?

  • 个人:写html、css、js
  • 大公司:工程化(自动化、模块化、性能优化)

自动化(命令行自动实时转译)

  • 用Less命令行将less自动转成css
  • 用Bable命令行将es6语法自动转成es5
  • 用Autoprefixer命令行将css3自动加上浏览器私有前缀

webpack模块自动化构建工具

什么是模块?在 webpack 下,所有类型的文件都可以是模块,包括 CSS、图片、JSON,等等。

前端工程化遇到的问题:

  1. Less、Babel、Autoprefixer等必须全部开着命令行监控文件的变化,才能实时自动转译。
  2. 前端发展很快,html–>pug–>slim, css–>less–>sass–>scss–>stylus, js–>es6–>Typescript

能不能不要开那么多命令行窗口呢?并且根据文件后缀名自动转成标准的前端文件呢?
用模块自动化构建工具(打包工具)!

模块自动化构建工具(打包工具)发展史

Grunt –> Gulp –> Webpack –> Parcel

项目目录结构

  • .bin:binary,可执行的
  • dist:distributable,可分发的
1
2
3
4
5
6
7
8
9
10
11
12
13
|
|
|-- src //source,未经转译过的源文件
| |-- imgs //图片放这里
| |-- js //原始js代码放这里
| |-- style //原始样式代码(.less,.scss,.sass)放这里
|
|-- dist //distribution,转译后的代码
| |-- index.html
|
|-- node_modules //通过npm下载的第三方库
|
|-- vendors //自己找的第三方库

使用步骤

  • 退出vim:esc +:+ w + q
  • $ node_modules/.bin/webpack –watch //监听变动并自动打包
  • $ node_modules/.bin/webpack -p //压缩混淆脚本,这个非常非常重要!
  • $ npm list -g –depth=0 查看所有全局安装
  1. 先全局安装[不推荐全局安装 webpack。这会将你项目中的 webpack 锁定到指定版本,并且在使用不同的 webpack 版本的项目中,可能会导致构建失败。]npm i webpack webpack-cli -g 进行全局安装【如果出现npm install出现”Unexpected end of JSON input while parsing near”错误,执行npm cache clean --force
  • 在项目目录下打开命令行,npm init -y初始化模块,生成package.json
  • npm i webpack webpack-cli -D-D表示--save-dev),安装webpack到当前目录(局部安装)
  • webpack装在了node_modules文件夹下一个.bin文件夹里(binary:可执行的)
  • 创建./src/index.js
  • 打开package.json并添加

    1
    2
    3
    4
    "scripts": {
    "dev": "webpack --mode development",
    "build": "webpack --mode production"
    }
  • 这样,在执行npm run dev时吐出未压缩的包,执行npm run build时吐出压缩后的包

webpack4

参考教材:https://blog.zfanw.com/webpack-tutorial/

默认入口和出口

  • 创建文件./src/index.js
  • 从webpack 4开始,不需要定义入口点:它会将./src/index.js作为默认值!【可以创建webpack.config.js进行修改】
  • 打开package.json并添加一个构建脚本:”scripts”: { “build”: “webpack”}保存并关闭文件
  • 执行npm run build,默认在 ./dist/main.js中获得该软件包。webpack4会查找./src/index.js作为默认入口点。 而且,它默认会在./dist/main.js中吐出这个包。
  • 创建./dist/index.html,并引入main.js

配置入口和出口

如果不想要默认配置,可以自定义配置

  • 新建webpack.config.js(这个配置文件可以拷贝官方文档)
    1
    2
    3
    4
    5
    6
    7
    module.exports = {
    entry: './src/a.js' //入口 a.js可以简写成a
    output: { //出口
    path: path.resolve(__dirname, 'dist'), //__dirname表示当前目录,后面的参数表示文件夹名
    filename: 'bundle.js'
    }
    };

这样,我们只需要执行npm run build,就可以将src下的a.js打包到dist下的bundle.js(压缩模式)


1
2
3
4
5
6
7
8
9
10
11
多入口,多出口配置
module.exports = {
entry: {
home: './src/home.js', //home.js可以简写成home
signup: './src/signup.js'
},
output: { //出口
path: path.resolve(__dirname, 'dist'), //__dirname表示当前目录,后面的参数表示文件夹名
filename: '[name].bundle.js' //生成home.bundle.js和signup.bundle.js
}
};

生产模式production和开发模式development

生产模式build:压缩,体积小
开发模式dev:未压缩,体积大

事实上,如果你注意npm run build的输出,你会看到一个很好的警告:

The ‘mode’ option has not been set. Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for this environment.(“mode”选项尚未设置。 将“mode”选项设置为“development”或“production”以启用此环境的默认值。)

打开package.json并添加

1
2
3
4
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
}

这样,在执行npm run dev时吐出未压缩的包,执行npm run build时吐出压缩后的包

配置环境process.env.WEBPACK_MODE

慕课网笔记:小记webpack4.x升级过程

在webpack.config.json填入set WEBPACK_ENV

1
"dev": "set WEBPACK_MODE=development && webpack --mode development

然后在webpack.config.js中就能获取到

1
console.log('process.WEBPACK_MODE : '+process.env.WEBPACK_MODE)

获取npm run xxx

npm 提供一个npm_lifecycle_event变量,返回当前正在运行的script名称,比如devbuildwatch

在webpack.config.json填入

1
2
var currentTarget = process.env.npm_lifecycle_event;
console.log('npm run : '+currentTarget)

文件实时更新【会自动更新mian.js】

打开package.json并添加

1
2
3
"scripts": {
"watch": "webpack --mode development --watch"
}

这样,执行npm run watch就可以实时监控文件,一旦文件有变化就自动更新

自动刷新浏览器【更新的文件保存在缓存中】

webpack-dev-server 为你提供了一个简单的 web 服务器,并且能够实时重新加载(live reloading)。
安装:npm i webpack-dev-server -D
打开package.json并添加

1
2
3
"scripts": {
"start": "webpack-dev-server --mode development --content-base ./dist --open",
}

这样,在执行npm start就会看到浏览器自动加载页面。

注意:你启动webpack-dev-server后,你在
./dist/main.js中是看不到编译后的文件的,实时编译后的文件都保存到了浏览器内存当中。因此很多同学使用webpack-dev-server进行开发的时候都看不到编译后的文件
【解决办法】多开一个命令行串口,用npm watch实时监控文件变动随时编译就行了。
webpack-dev-server的端口怎么修改?
【解决方法】用–port来制定参数,比如webpack-dev-server --port 8888

配置命令详解

1
2
3
4
5
"scripts": {
"build": "webpack --profile --progress --colors --display-error-details",
"dev": "webpack --display-modules --profile --progress --colors --display-error-details",
"start": "webpack-dev-server --config"
}
  • color 输出结果带彩色,比如:会用红色显示耗时较长的步骤
  • profile 输出性能数据,可以看到每一步的耗时
  • progress 输出当前编译的进度,以百分比的形式呈现
  • display-modules 默认情况下 node_modules 下的模块会被隐藏,加上这个参数可以显示这些被隐藏的模块
  • display-error-details 输出详细的错误信息
  • webpack-dev-server 将会开启热更新
  • 更多请参考官网 cli

LOADER转译器

Webpack 本身只能处理 JavaScript 模块,如果要处理其他类型的文件(ES6,less,sass,scss等),就需要使用 loader 进行转换。

css相关loader

sass-loader 把sass转成css
css-loader 会遍历 CSS 文件,然后找到 url() 表达式然后处理他们
style-loader 把CSS 代码插入页面中的一个 style 标签中。

sass-loader

npm i -D css-loader style-loader
npm i -D sass-loader node-sass
npm i -D less less-loader
npm i -D extract-text-webpack-plugin@next
npm i -D postcss-loader //添加前缀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
创建postcss.config.js
module.exports = {
plugins: {
'postcss-import': {},
'postcss-cssnext': {},
'cssnano': {} //压缩css代码
}
}
```
在index.js中将样式表引入`import ../css/style.scss`
### babel-loader
npm i -D babel-core babel-preset-env babel-loader
在webpack.config.json填入
```javascript
module: {
rules: [{
test: /\.js$/, //以.js结尾的文件
exclude: /(node_modules|bower_components)/, //排除
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
}]
}

babel-polyfill转换es6的api

Babel默认只转换新的JavaScript句法(syntax),而不转换新的API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(比如Object.assign)都不会转码。举例来说,ES6在Array对象上新增了Array.from方法。Babel就不会转码这个方法。如果想让这个方法运行,必须使用babel-polyfill

Babel默认不转码的API非常多,详细清单可以查看babel-plugin-transform-runtime模块的definitions.js文件。

1
2
3
4
5
6
7
8
9
10
安装:
npm i babel-polyfill -S
然后需要时,在入口文件最顶部通过 import 将 polyfill 引入
import "babel-polyfill";
或者直接暴力在 webpack.config.js 中,将 babel-polyfill 加到你的 entry 数组中:
module.exports = {
entry: ["babel-polyfill", "./app/js"]
};

上面这种方法将整个polyfill引入,会导致文件过大!

core-js转换es6的api

推荐手动引入core-js
使用方法:

1
2
3
4
5
6
7
8
9
10
11
在入口文件的顶部引入
import 'core-js/fn/object/assign';
import 'core-js/fn/string/repeat';
如何就可以在自己的js文件中用Object.assign、str.repeat了
var data = {a:1}
Object.assign(data,{b:2,c:3});
console.log(data);
var x = 'h'.repeat(10);
console.log(x);

参考内容:

purifycss去除无用css

安装:npm i -D purifycss-webpack purify-css

在webpack.config.js中配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const glob = require("glob");
const PurifyCSSPlugin = require("purifycss-webpack");
//插件:用于生产模板和各项功能
plugins:[
//把CSS独立出来,不要打包到js文件中去里面写的就是独立出来后的路径
new extracTextPlugin("/css/index.css"),
//去除无用css(必须配合extract-text-webpack-plugin这个插件)
new PurifyCSSPlugin({
paths:glob.sync(path.join(__dirname,"src/*.html"))
})
]

常用指令

用npx可以自动找到命令行工具所在位置,比如npx webpack --mode development --watch等同于./node_modules/.bin/webpack --mode development --watch
这样就不需要安装到global全局也能使用,比如原本http-server要安装到全局,然后才能http-server -c-1 -o,现在可以不安装到全局,直接npx http-server -c-1 -o打开

  • npx webpack -v:查看webpack版本号
  • npm run dev 打包成不压缩的文件
  • npm run build 打包成压缩文件
  • npm run watch 启动watch监视,并实时打包成新文件
  • npm run start 打开本地服务器调试

导入导出modules

导出

1
2
属性:module.exports.age=12;
方法:module.exports.sayAge=function(){}

具体如下

1
2
3
4
5
6
7
8
9
10
//login.js
{
let userName="stage";
module.exports.userName=userName;
module.exports.sayName=function(){
return userName;
};
}

引入

1
2
import loadsh from 'lodash' // 从模块目录查找
import a from './src/js/a.js' // 按相对路径查找【文件的后缀名可加可不加】

这里注意一下:模块查找和相对目录的查找的写法,模块查找是不需要”./“,直接写上模块名字,这里的模块一般是通过npm i下载到node_modules的模块。

具体如下

1
2
3
4
{
import xxx from './src/js/login.js';//引用模块
alert(xxx.sayName());//使用 引用模块的方法
}

去除.map文件

打包时不要map文件:

1
2
去config/index.js中改一个参数:
productionSourceMap:false

发布到githut

  • 将config -> index.js 里build配置项里的assetsPublicPath修改成这样→assetsPublicPath: './',

关于-D和-S

https://segmentfault.com/p/1210000009653830/read

  • npm i xxx -D:模块名将被添加到 devDependencies 开发依赖,在我们开发的时候会用到的一些包,只是在开发环境中调试时需要用到的包
  • npm i xxx -S:模块名将被添加到 dependencies
  • npm在下载模块时,默认-S,所以npm i xxx等同于npm i xxx -S

面试题

http://ovenzeze.coding.me/

-------------本文结束感谢您的阅读-------------