【webpack】1


前端模块化基于html的,在html里只需要引用一个模块,然后在这个模块里引用别的模块,自动加载别的模块

  例如,我们新建一个main.js 用于整合js,在这里面引其他的文件,通过main.js 自动把其他js加载进来

1.关于模块:

  • node的模块分为:自定义、第三方和内置
  • 模块的概念只针对js文件,css\html不行,所以模块一般特指的就是js文件
  • 不同模块都遵循各自规范:
  1. node模块的规范是commonjs,这个规范定义了:如何引用、如何导出、如何定义
  2. 除了commonjs规范外,前端也有一些规范:cmd(seajs-define) / amd(requirejs引入一些模块),这些都是一些规范
  3. 为什么出现cmd/amd这些规范,因为以前前端不支持模块化,但是现在es6已经兼容了模块化(esmodule–es的模块),我们可以基于es6来使用一些模块了

问题: seajsrequirejsesmodulecommonjs的区别?

  1. seajsrequirejs
    seajsrequirejs是人家写好的规定的写法;
    seajsrequirejs 是一个帮我们实现模块化的库,还需要引用这个库
  2. commonjs
    commonjsnode的规范,只能在编辑器里右键 run,不能直接在浏览器里运行;而import不能在编辑器里右键run
    let a = require('../') 这种写法是node的写法,不能再前端使用,而且前端也没有require 这个关键字,会报错require is not defined

在commonjs中/也就是在nodejs中,
1. 定义模块:一个js文件就是一个模块;
2. 导出模块:exports 或者 module.exports
3. 引入模块:require

  1. esmodule:

关于esmodule:
1. 定义模块:一个js就是一个模块
2.导出模块: export (注意es6 没有s)
3.引入模块:import

es6的模块化可以在浏览器中用

注:umd – 用来兼容处理,用了它之后可以既支持cmd 又支持amd 又支持commonjs规范

2.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>
    <!--
    chrome要62以上,如果不支持,可以借用第三方的插件(库)去解析,放在引入模块的文件的上面
    引入后,又会帮我们解析一次,如果浏览器可以解析,就可以执行两次,浏览器解析一次,这个包解析一次
    
    <script src="https://google.github.io/traceur-compiler/bin/traceur.js"></script>
    <script src="https://google.github.io/traceur-compiler/bin/BrowserSystem.js"></script>
    <script src="https://google.github.io/traceur-compiler/src/bootstrap.js"></script> 
    -->
    <script src='main.js' type='module'></script>
    <!-- 引模块,要加type='module' 说明引的是个模块,按模块的规则来解析 
        如果没有反应的话:因为浏览器把这个js当成模块加载了,这种模块语法是es6支持的,如果浏览器的版本太低,就解析不出js里的内容,
    -->
</body>
</html>

3.esmodule 的写法

  1. 在a.js里定义和导出:可以导出 变量 、方法 和 默认导出
//要在main.js里引入这两个变量,这里要先导出变量

export let str1 = '这是a.js里的变量1';
export let str2 = '这是a.js里的变量2';

/* 
    这些写的实现:会将str1 和 str2放到一个对象里导出,然后在main.js里引入
    {str1:'这是a.js里的变量1',str2:'这是a.js里的变量2'} 
*/

/* 
    node的commonjs规范的写法是:

    exports.str1 = str1;    
    exports.str2 = str2; 
    //最后导出exports对象

*/

// 导出方法/函数
export function a(){
    console.log('a方法');
}
//导出箭头函数
export let c = ()=>{
    console.log('c方法');
    
}
// 默认导出:可以是变量 对象 方法都可以
export default {
    m:999,
    n:'你好'
}
//let  a = 'c.js里的默认导出';
//export default a; 
  1. 在main.js里引入模块:
  • 模块引入的时候:如果是第三方模块,不需要加./ ;如果是文件模块(自己写的js)需要加 ./
//通过main.js来引其他的js

/*
    import './a.js';   
    //这里 .js 可以省略,这只是引入了js,但是要直接在这个js文件用a.js里的导出,需要放到变量上;
    //let a = require('./a.js');    //就像这里的commonjs写法,commonjs里的写法,带有变量a 
*/

// -----------------------
    console.log(str1);  //import 具有提升效果,可以预解析;可以在import前拿到;
    import {str1,a as b,c} from './a.js';   
    // a.js里会将str1 和 str2放到一个对象里导出,所以这里引入的时候,应该放一个 对象  和 a.js 相匹配
    // 这样的写法用到了  解构赋值:在另一个文件中将内容结构出来即可使用

    // import a from './a.js';     //这样写需要在 a.js里写一个名字是default的导出,作为默认导出

    console.log(str1);
    b();   //引入的方法名要和导出的一样,可用as 修改命名
    c();
    //问题1:上面的写法很复杂,要导出的变量很多时很麻烦;
    //注意1:而且  import {str1} from './a.js';   里面的结构赋值 let {str1} = {str1:111};相当于把str1声明过了,下面就不能再声明这个变量了
            //import 拥有声明功能,下面就不能再声明和他一样的变量了;
    //注意2:import 具有提升效果,可以预解析;可以在import前拿到;但最好import放到顶部;

// ---------------------------------------------
    // 作为一个对象引入 
    import * as d from './b.js';
    // * 代表输出的所有的, as b 这样写b就是一个对象了(导出所有的放到* 中,并重命名为d)
    console.log(d.str3);

    import m from './b.js'; //k 是b.js里 export default后面的内容,后面是个对象,所以k是个对象
    console.log(m);
    

//-------------------------
import xx from './c.js';
console.log(xx);



// esmodule 的要求:1.要求谷歌必须62以上的(而且es6语法,箭头函数什么的解析不了)

/* 
我们希望:
1.语法问题,可以把高级语法转成低版本语法,babel 翻译器,可以把es6,es7 翻译成es5
2.模块问题:代码中可能会有import语法,这在低版本浏览器也不认识,我们希望模块 转成闭包 ,webpack--一个打包器
 */

/* webpack 是一个 模块加载器  兼  打包工具(可以把各种资源js,css进行自动编译)

雪碧图还是要发请求,如果图片比较小的,我们希望转成base64,这样就可以不发请求了,都可以用webpack

1. webpack 是基于commonjs的规范来写的,写法是node的写法,但对AMD,cmd 也支持;
2.能被模块化的不仅仅是js(以前模块只针对js文件),webpack也可以支持图片,css,less,sass
3.我们写的代码怕被别人拷走,所以上线的时候打包,混淆压缩;还可以图片转base64等,能替代部分gulp的工作;
4.写代码时以保持,页面就自动更新,不用刷浏览器,刷浏览器很耗性能;

webpack -模块处理器:处理各种依赖关系,天然可以处理模块的问题 */

打包一个文件配置

webpack.config.js页面:

let path = require('path');
//peth是node的内置模块,用来处理路径的;最常用的方法是resolve()

path.resolve('./dist');  //以当前路径解析出一个绝对路径
console.log(path.resolve('./dist'));

//resolve是解析,给他一个相对路径,会返回一个绝对路径;

//webpack 必须采用commonjs的写法,不能用es6或其他的;
// 规定的是要导出一个模块module.exports = {}
module.exports = {
    entry:'./src/main.js',    
    //打包的入口文件,webpack会自动查找相关的依赖进行打包
    //在main.js里引了一些其他的js文件
    output:{
        filename:'bundle.js',   //打包后的名字
        path:path.resolve('./dist'), //必须是一个绝对路径,打包文件放的位置
        // c://xx/xx/index.js  这是绝对路径;  ./a/index.js  这是相对路径
        // path:__dirname+'/dist',   //__dirname 是目录名,是个绝对路径,这样写也可以
    }
}

打包多个文件的配置

多入口打包,配置webpack.config.js页面:

let path = require('path');
// path.resolve('./dist');  //以当前路径解析出一个绝对路径

module.exports = {
    entry:{   //多文件打包,入口文件放在对象里
        main1:'./src/main1.js',
        main4:'./src/main2.js'
    },    
    output:{
        filename:'[name].js',   
        //出口的文件,[name]会自动匹配对象里的key的名字
        path:path.resolve('./dist'), 
    }
}

babel 将es6转译成es5

  1. 先安装babel,也是只在本地用,转移完上线的时候不用
npm install babel-core  --save-dev
npm install babel-loader  --save-dev

babel-core是babel的核心包,babel-loader 基于babel-core,babel-loader是用来解析语法的;(core相当于转译器,loader是加载器,用来解析语法的)

  1. babel-preset-es2015 做一些预设:让翻译官babel-loader拥有解析es6语法的功能
npm install babel-preset-es2015  --save-dev

安装完这个后,会生成很多个小包,以babel-plugin-开头的一些插件

  1. 新建一个文件.babelrc,这这里面写一些预设,在babel-loader编译的时候,会到这个``文件里找,是不是会编译目标语言;
{
    "presets":["es2015"]
}

注意:是presets,有s

  1. 在webpack.config.js里配置模块解析规则:
let path = require('path');
// path.resolve('./dist');  //以当前路径解析出一个绝对路径

module.exports = {
    entry:'./src/main.js',    
    output:{
        filename:'bundle.js',   
        path:path.resolve('./dist'), 
    },
    // 模块的解析规则
    module:{
        rules:[
           {
            test:/\.js$/,
            use:'babel-loader',
            exclude:/node_modules/,
        } 
           //用正则匹配,/\.js$/以.js结尾的,exclude排除掉xx
            //匹配所有.js,用babel-loader转译,排除掉node_modules
        ]
    }
    // js: 匹配除node_module以外的所有.js后缀的文件,用babel-loader进行转译,转成es5;
}

将es7 转成es5

下面的就是es7语法:

let obj1 = {name:'lxz'};
let obj2 = {age:18};

let newObj = {..obj1,..obj2};   //这是es7语法
  1. 安装babel-preset-stage-0用来解析es7语法,0 包含了所有的,babel-preset-stage-4是es6
npm install babel-preset-stage-0  --save-dev
  1. 修改.babelcr
{
    "presets":["es2015","stage-0"]
}

解析样式

1. 打包.css文件到js模块里

之前我们都是在html里引css,如果想在js中引用css,想把css当成模块进行加载;webpack默认只认js,但是可以通过一些手段认识css

  1. js文件中引css:
    在main.js里,引入css,require 和import都可以,但css是前端的,推荐用import引
import './index.css'
  1. 引入css后不识别,安装一个可以识别的模块css-loader
npm install css-loader style-loader --save-dev

解析成css后还得放到html页面上,我们可以通过link标签引进来;也可以通过style标签,把文件写到style标签里,可以用style-loader

css-loader将css解析成模块,style-loader将解析的内容插入到style标签里

  1. 配置webpack.config.js文件
let path = require('path');
// path.resolve('./dist');  //以当前路径解析出一个绝对路径

module.exports = {
    entry:'./src/main.js',    
    output:{
        filename:'bundle.js',   
        path:path.resolve('./dist'), 
    },
    // 模块的解析规则
    module:{
        rules:[
           {             // js: 匹配除node_module以外的所有.js后缀的文件,用babel-loader进行转译,转成es5;
            test:/\.js$/,   //用正则匹配,/\.js$/以.js结尾的,exclude排除掉xx
            use:'babel-loader',
            exclude:/node_modules/,    //匹配所有.js,用babel-loader转译,排除掉node_modules
        },{
            test:/\.css$/,
            use:['style-loader','css-loader'],    // 这里数组里要 从右往左写,先在右边写css-loader,然后写左边style-loader
        }
           
        ]
    }
    
}

打包完后,css样式是被打包到bundle.js里;

2. 打包.less文件到js模块里

  • less是css预处理语言;不是写的真的css,写完后帮我们处理成css;
  • 常见的有:less,sass,stylus ,编译他们需要各自对应的loader

编译less需要less-loader , less , css-loader , style-loader

  1. 用less要先安装less模块,建议安装局部的,以保证版本的一致性;并且也要用到css-loader 和 style-loader;
npm install less less-loader --save-dev

less的好处可以写嵌套语法;
2. 配置webpack.config.js文件

let path = require('path');
// path.resolve('./dist');  //以当前路径解析出一个绝对路径

module.exports = {
    entry:'./src/main.js',    
    output:{
        filename:'bundle.js',   
        path:path.resolve('./dist'), 
    },
    // 模块的解析规则
    module:{
        rules:[
           {             // js: 匹配除node_module以外的所有.js后缀的文件,用babel-loader进行转译,转成es5;
            test:/\.js$/,   //用正则匹配,/\.js$/以.js结尾的,exclude排除掉xx
            use:'babel-loader',
            exclude:/node_modules/,    //匹配所有.js,用babel-loader转译,排除掉node_modules
        },{
            test:/\.css$/,
            use:['style-loader','css-loader'],    // 这里数组里要 从右往左写,先在右边写css-loader,然后写左边style-loader
        },{
            test:/\.less$/,
            use:['style-loader','css-loader','less-loader'],    // 这里数组里要 从右往左写,先在右边写css-loader,然后写左边style-loader
        }
           
        ]
    }
    
}

解析图片

1. 解析css里引的图片

我们解析图片的时候需要用到url-loader, url-loader依赖于file-loader,所以安装的时候都要安装,用的时候只用url-loader

  1. 下载依赖的包
npm install less file-loader url-loader --save-dev

2.在webpack.config.js里写解析规则

let path = require('path');
// path.resolve('./dist');  //以当前路径解析出一个绝对路径

module.exports = {
    entry:'./src/main.js',    
    output:{
        filename:'bundle.js',   
        path:path.resolve('./dist'), 
    },
    // 模块的解析规则
    module:{
        rules:[
           {             // js: 匹配除node_module以外的所有.js后缀的文件,用babel-loader进行转译,转成es5;
            test:/\.js$/,   //用正则匹配,/\.js$/以.js结尾的,exclude排除掉xx
            use:'babel-loader',
            exclude:/node_modules/,    //匹配所有.js,用babel-loader转译,排除掉node_modules
        },{
            test:/\.css$/,
            use:['style-loader','css-loader'],    // 这里数组里要 从右往左写,先在右边写css-loader,然后写左边style-loader
        },{
            test:/\.less$/,
            use:['style-loader','css-loader','less-loader'],    // 这里数组里要 从右往左写,先在右边写css-loader,然后写左边style-loader
        },{
            test:/\.(jpg|png|gif|svg)$/,
            use:['url-loader?limit=8192'],    // 图片会给转成base64,我们可以限制8k(8*1024=8192字节)一下的转base64,其他情况下输出图片
        }
           
        ]
    }
    
}

这样解析成的图片会给转成base64,转成字符串base64后,就不会再发请求了
但是我们希望大的图片还是实体文件,小的图片才转base64

2. 解析js里引的图片

在js里引入图片需要import,或者写一个线上路径;

import page from './1/jpg';  //webpack找到依赖的图片1.jpg 进行打包,打包后的路径放在page里

let img = new Image();
img.src = page;  //page是打包后图片的路径
// img.src = './1/jpg';  //这样写,webpack会认为这是一个字符串,不会进行查找解析,所以相对的不可以,但是线上的路径本来就是个字符串,是可以正常显示的
document.body.appendChild(img);

解析html的插件

  1. 安装插件 html-webpack-plugin

html-webpack-plugin插件的作用:以自己的html为模板,将打包后的结果 自动引入到html中,产出到dist目录下

上面说的loader 是用来解析模块的;这里的插件是用来给webpack加一些新的功能的;

npm install html-webpack-plugin --save-dev

html-webpack-plugin 是个第三方模块(插件),用之前需要自己先引入
他可以帮我们把html输出到dist下,而且自动引入打包的js文件;
在webpack.config.js中:

let HtmlWebpackPlugin = require('html-webpack-plugin');
let path = require('path');
// path.resolve('./dist');  //以当前路径解析出一个绝对路径
let HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry:'./src/main.js',    
    output:{
        filename:'bundle.js',   
        path:path.resolve('./dist'), 
    },
    // 模块的解析规则
    module:{
        rules:[
           {             // js: 匹配除node_module以外的所有.js后缀的文件,用babel-loader进行转译,转成es5;
            test:/\.js$/,   //用正则匹配,/\.js$/以.js结尾的,exclude排除掉xx
            use:'babel-loader',
            exclude:/node_modules/,    //匹配所有.js,用babel-loader转译,排除掉node_modules
        },{
            test:/\.css$/,
            use:['style-loader','css-loader'],    // 这里数组里要 从右往左写,先在右边写css-loader,然后写左边style-loader
        },{
            test:/\.less$/,
            use:['style-loader','css-loader','less-loader'],    // 这里数组里要 从右往左写,先在右边写css-loader,然后写左边style-loader
        },{
            test:/\.(jpg|png|gif|svg)$/,
            use:['url-loader?limit=8192'],    // 图片会给转成base64,我们可以限制8k(8*1024=8192字节)一下的转base64,其他情况下输出图片
        }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({   //以自己的html为模板,将打包后的结果 自动引入到html中,产出到dist目录下  
            template:'./src/index.html',   //使用的模板:自己定义的模板
            filename:'login.html'    //产出的文件的名字:可以修改输出到dist下的html的文件名
        }),
    ]
    
}

webpack-dev-server 开发服务

  1. 我们每次npm run build 都算是读写文件,从src里读然后写到dist里,这是通过node做的;IO读写浪费性能;

  2. 我们希望代码上线的时候再产生dist,在开发的时候不用;

  3. 所以我们希望在不产生dist下文件的情况下还能看到效果,webpack给我们提供了一个服务webpack-dev-server,这个服务可以给我们展示代码的效果

  4. webpack-dev-server里面内置了服务,可以帮我们启动一个端口号,当代码更新时,可以自动打包(在内存中打包,不产生实体文件),而且时刻监控代码,代码有变化就重新执行

npm install webpack-dev-server --save-dev
  1. 配置package.json里的脚本:
  "scripts": {
    "build": "webpack",
    "dev":"webpack-dev-server"
  },

如上配置,我们npm run build 的时候走的是node_modules下.bin里的webpack.cmd;–用于放生产前打包
npm run dev的时候运行的是node_modules下.bin里的webpack-dev-server命令 --用于开发时起服务

运行npm run dev 会帮我们启动一个服务器,打开一个网页,端口号默认8080;默认情况下打开的是index.html

.vue文件

以前在html里用script引js,现在是在js里用import引入js

import Vue from 'vue';
//这样引入vue,引用的并不是vue.js,引用的是vue的runtime.common.js

vue由两部分组成,
vue = compiler(编译用的,compiler可以编译模板) + runtime

‘vue’ 是第三方模块,不用加./,找的时候去node_modules下vue文件夹下的package.json里main对应的文件"main": "dist/vue.runtime.common.js"

第三方模块查找就是通过node_modules下vue文件夹下package.json找main对应的文件

  1. .less 需要用less-loader解析,同样.vue webpack也不认识,需要vue-loader来解析,而且vue-loader还依赖一个编译模板vue-template-compiler(因为上面引vue的时候引的是runtime,没引compiler)
npm install vue-loader vue-template-compiler --save-dev
  • vue-loader 用来解析.vue文件的,vue会自动的调用vue-template-compiler
  • vue-template-compiler 用来解析vue模块的
  1. 配置webpack.config.js文件
let path = require('path');
// path.resolve('./dist');  //以当前路径解析出一个绝对路径
let HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    entry:'./src/main.js',    
    output:{
        filename:'bundle.js',   
        path:path.resolve('./dist'), 
    },
    // 模块的解析规则
    module:{
        rules:[
           {             // js: 匹配除node_module以外的所有.js后缀的文件,用babel-loader进行转译,转成es5;
            test:/\.js$/,   //用正则匹配,/\.js$/以.js结尾的,exclude排除掉xx
            use:'babel-loader',
            exclude:/node_modules/,    //匹配所有.js,用babel-loader转译,排除掉node_modules
        },{
            test:/\.css$/,
            use:['style-loader','css-loader'],    // 这里数组里要 从右往左写,先在右边写css-loader,然后写左边style-loader
        },{
            test:/\.less$/,
            use:['style-loader','css-loader','less-loader'],    // 这里数组里要 从右往左写,先在右边写css-loader,然后写左边style-loader
        },{
            test:/\.(jpg|png|gif|svg)$/,
            use:['url-loader?limit=8192'],    // 图片会给转成base64,我们可以限制8k(8*1024=8192字节)一下的转base64,其他情况下输出图片
        },{
            test:/\.vue$/,
            use:['vue-loader'],   //vue会自动的调用vue-template-compiler,就不用配vue-template-compiler了
        }
        ]
    },
    plugins:[
        new HtmlWebpackPlugin({   //以自己的html为模板,将打包后的结果 自动引入到html中,产出到dist目录下  
            template:'./src/index.html',   //使用的模板:自己定义的模板
            filename:'login.html'    //产出的文件的名字:可以修改输出到dist下的html的文件名
        }),
    ]
    
}

  1. 使用.vue文件
import Vue from 'vue';
//这样引入vue,引用的并不是vue.js,引用的是vue的runtime.common.js
//vue = compiler(编译用的,compiler可以编译模板) + runtime

import App from './App.vue'   //自己写的文件模块加./
console.lgo(App);  //app 是个组件,组件是一个对象,这个对象可以通过createElement()创建成一个虚拟dom,然后通过render函数将虚拟dom渲染成真实的dom

new Vue({
	//createElement() 返回的是虚拟dom
	//render函数将虚拟dom渲染成真实的dom
	render:function(createElement){  //因为引的是vue.runtime.common.js  没有compiler,所以要用render渲染
		return createElement(App);
	}
	// render:(h)=>h(App)  render可以简写成这样
}).$mount('#app')   //等价于在配置里写 el:'#app'

vue-loader的作用是把.vue文件变成一个模块

发布了57 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Eva3288/article/details/104438781