一、安装
webpack 是一个模块开发工具。它的主要目标是将 JavaScript 文件打包在一起,打包后的文件用于在浏览器中使用,但它也能够胜任转换 (transform)、打包(bundle)或包裹(package)任何资源(resource or asset)。webpack 就两个作用一个打包作用,一个用于翻译作用。
webpack是 nodejs 的工作流工具,首先进行安装:
cnpm install -g webpack webpack-cli
cli 是英语 commond line interface 命令行接口的意思。
webpack 和其插件 webpack-cli
安装完毕之后,查看版本号:
4.35.2
二、基本使用
我们的项目很简单,没有任何的第三方库,没有sea.js、没有require.js。写法几乎和 node.js 写法没什么区别。
程序也很简单,所有的js文件都在裸奔CMD规范,没有任何的标准壳:
//circle.js
function mianji(a,b){
return a * b ;
}
exports.mianji = mianji;
//main.js
const c = require("./circle");
alert(c.mianji(10,10)) ;
浏览器不支持、不兼容任何的require、exports单词。所以直接运行浏览器报错。使用webpack可以轻松解决这个事情!
这时我们在CMD窗口中执行:
webpack main.js -o ./dist/all.js
o是output输出的意思。
把main.js 和里面的引报包合并到 dist 文件目录下all.js (没有文件目录自动创建)
合并的 all.js
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){const r=n(1);alert(r.mianji(10,10))},function(e,t){t.mianji=function(e,t){return e*t}}]);
可以看到代码前部分算是CMD规范的定义,最后几句给我们写的代码加上了标准壳。
//index.html
为什么说webapck是智能打包、智能合并?
- webpack不是无脑合并js文件!和我们今后要学习的Grunt、Gulp不同;
- webpack是按图索骥的,只有require链中出现的js文件,才会被打包到all.js文件中!
- 如果多个文件都require了某文件,这个文件只会在all.js中出现一次。
三、 webpack.config.js 文件
很明显,每次直接输入是非常狼狈的。
webpack提供了一个文件可以配置它,指导webpack工作。这个文件的名字叫做webpack.config.js。名字必须是这个,必须放在项目的根目录。
这个文件模式背诵:
var path = require("path");
//进行配置的东西,实际上是本文件的暴露项,要写module.exports
module.exports = {
//配置模式,有两个单词可以选择
//development开发模式,代码不会混淆、压缩;
//production生产模式,项目上线的时候要使用的模式。
mode: "development",
//配置入口文件
entry : "./js/main.js" ,
//配置产出文件
output : {
//产出文件文件夹
path : path.resolve(__dirname , "dist") ,
//产出文件的文件名
filename : "all.js"
},
//实时监测文件更新,一旦文件更新了,就重新合并打包一份
watch : true
}
写完这个文件之后,我们就能在项目的根目录打开CMD窗口,输入简单的命令:
webpack
webpack就知道自己找入口文件了,自己合并到产出文件了,自己监听文件的变化了。
更加自动的方式,创建身份证。
npm init
在身份证中改变一下 scripts:
{
"name": "my",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev" : "webpack"
},
"author": "",
"license": "ISC"
}
今后起项目就可以:
npm run dev
三、 babel-loader
Babel是一个转换编译器,它能将 ES6 转换成可以在浏览器中运行的代码。软件的目的让开发者使用更新的语法,同时不用担心浏览器的兼容问题。
cnpm install babel-core@6 babel-loader@7
安装的时候一定要注意,babel 最新版本 8 代和 webpack4 有兼容问题,只能指定老版本。
babel-core是babel的核心,babel-loader 是 webpack 插件。
通过看手册,我们知道修改 webpack.config.js 文件:
module: {
rules: [
{
test: /\.m?js$/,//匹配.mjs和.js结束的文件
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
}
]
}
所谓的 preset 是什么意思呢?preset表示预设置。表示可以把高级语言翻译成低级语言例如 ES6 => ES5。
npm install --save babel-preset-env
依据下图可发现我们在配置的时候,会把 babel- 后面第一个值的作为属性名,最后一个值作为属性值。
可以进行项目启动
npm run dev
可以看见 ES6 被翻译成普通 JS语法。
为了让babel能够翻译…
语法,我们必须安装一个babel的插件,
babel-plugin-transform-object-rest-spread
安装依赖:
cnpm install babel-plugin-transform-object-rest-spread
改变webpack.config.js文件:
module: {
rules: [
{
test: /\.m?js$/,//匹配.mjs和.js结束的文件
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env'],
plugins: ["transform-object-rest-spread"]
}
}
}
]
}
此时就可以npm run dev
:
const obj2 = {
...obj,
}
四、ES6中的CMD语法
CMD语法是commonjs在2005年左右提出的语法,被nodejs全盘采纳。
脑残的 w3c 却非得这样定义:
ES6对应CMD简单的对应关系:
require变为了import
exports变为了export
module变为了default
控制台输入测试:
浏览器厂商对此很抗议,到今天2019年7月5日,没有任何浏览器支持上述语法。
但是webpack支持,webpack在没有babel-loader的存在下,天生能够识别import的导入语法,从而进行智能的文件合并。
- 基本的暴露和引入
//circle.js
export const mianji = function (a,b){
return a * b ;
}
//main.js
import {mianji} from "./circle.js";
var a = prompt("下午好,请输入一个数");
var b = prompt("下午好,请输入另一个数");
alert(mianji(a,b));
必须在export后面加上const或者let或者var。大括号中的函数名字,必须严格和暴露的名字相同!
- 命名空间
如果两个包中都有mianji函数,此时用import {mianji}就冲突了。
就需要使用命名空间,必须使用import * as 名字 from ""
这样的语法:
import * as m from "./circle.js";
var a = prompt("下午好,请输入一个数");
var b = prompt("下午好,请输入另一个数");
alert(m.mianji(a,b));//请注意这里的调用不同
- 默认暴露
导入的时候,普通暴露加大括号,默认暴露不加大括号,中间用逗号隔开。
//circle.js
export const mianji = function (a,b){
return a * b ;
}
var m =6;
export default m;
//main.js
import m,{mianji} from "./circle.js";
var a = prompt("下午好,请输入一个数");
var b = prompt("下午好,请输入另一个数");
alert(mianji(a,b));
alert(m);
五、less 变为 CSS
less-loader:https://www.npmjs.com/package/less-loader
CSS 样式表是扁平化链式语法。
less 让样式表更加立体化。
body{
background:aquamarine;
@c : orange; //变量
h1{
color : @c;
}
}
但是浏览器识别不了此种语法,我们需要安装less和 less-loader、style-loader、css-loader 三个插件转化一下。
打开 webpack.config.js
//配置插件
module: {
rules: [
{
// 以less结尾的文件
test: /\.less$/,
use: [
{
loader: "style-loader" // creates style nodes from JS strings
},
{
loader: "css-loader" // translates CSS into CommonJS
},
{
loader: "less-loader" // compiles Less to CSS
}
]
}
]
}
引入后import "./me.less";
运行 npm run dev
打开网页即生效。
手动转less文件,未全局安装的时候。在这里找到node_modules\.bin
lessc
运行 CMD 命令 lessc a.less b.css
=> a.less 就变成了 b.css