博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
渐进式配置webpack4单页面和多页面(一)
阅读量:6778 次
发布时间:2019-06-26

本文共 12393 字,大约阅读时间需要 41 分钟。

渐进式配置webpack4单页面和多页面

前言

使用包的版本

webpack ->4.3.0babel-loader ->8.0.5npm ->6.4.1webpack-cli ->3.3.1复制代码

每个章节对应一个demo

一、初始化项目

进入项目目录,运行 npm init来创建项目

npm init复制代码

终端输入完成后会自动创建一个package.json的文件。

{  "name": "demo1",  "version": "1.0.0",  "description": "webpack-demo",  "main": "index.js",  "scripts": {    "test": "echo \"Error: no test specified\" && exit 1",    "build": "webpack app.js"  },  "keywords": [    "demo"  ],  "author": "cmf",  "license": "ISC",  "devDependencies": {}}复制代码

运行命令,引入webpack和webpack-cli,安装webpack-cli是为了在项目里面运行webpack命令。

npm i webpack webpack-cli -D复制代码

手动创建webpack.config.js。

touch webpack.config.js复制代码

在终端里面通过运行webpack命令无法进行复杂配置。所以创建webpack.config.js是为了后面的复杂配置。 新建app.js、index.html、view文件夹、view文件夹里面创建dom.js。

mkdir view touch app.js cd view  touch app.js复制代码

代码内容详见 配置 webpack.config.js

打包方式有两种

  • 通过npx命令
npx webpack复制代码
  • 通过配置package.json的script对象。
"scripts": {    "build": "webpack"  },复制代码

这两种方式都会自动寻找项目里面的webpack包进行打包,并且webpack会根据webpack.config.js的配置规则进行打包。


二、配置开发和生产环境

  • 开发环境特点
  1. 可视化
  2. 本地服务
  3. 可以快速找到代码错误
  4. 热更新
  • 生产环境特点
  1. 代码压缩
  2. 代码拆包
  3. 快速响应

下载插件包

npm i cross-env html-webpack-plugin webpack-dev-server -D复制代码

跨平台的解决了环境变量和参数的命令配置。

打包生成HTML的插件。
创建开发服务器。功能强大,接口转发、热更新等。

文件更改

新建index.html、help.js

touch index.htmltouch help.js复制代码

index.html 模板文件

  demo2  
复制代码

help.js 封装的一些方法。

module.exports.getMode = function() {  return process.env.NODE_ENV === 'development'?'development':'production'};复制代码

配置更改

其他配置请参考官方文档。

模式。默认值是production。 告知 webpack 使用相应模式的内置优化。是 webpack4新增的属性。比如mode是production,webpack会默认添加一些打包插件比如:NoEmitOnErrorsPlugin。可以节省很多配置。

命令配置

"scripts": {    "test": "echo \"Error: no test specified\" && exit 1",    "build": "cross-env NODE_ENV=production webpack",    "dev": "cross-env NODE_ENV=development webpack-dev-server"  },复制代码

cross-env NODE_ENV=production 设置环境变量信息

npm run dev复制代码

自动打开浏览器,会把app.js里面的内容自动注入到index.html里面。

三、模板解析与外部扩展

代码内容详见

外部扩展(externals)

防止将某些 import 的包是从外部获取依赖不是从node_modules里面获取的。

例如我们在app.js里面

// app.jsimport Vue from 'Vue';复制代码

index.html

  demo4  
复制代码

webpack.config.js

externals:{ //外部扩展    'Vue':'window.Vue'},复制代码

现在app.js 里面引入的Vue是从cdn里面引入的,而不是从node_modules包里面引入的。 这样做的好处:

  • 提高打包效率。
  • 类似于使用Vue这样的框架,使用的版本是一般是固定不变的。所以cdn引入的时候相当于模块化拆包。用户刷新浏览器和代码重新打包发版都不会再次请求Vue的代码,提高用户体验。

模板解析(resolve)

开发者可以自定义解析规则。

  • 自定义依赖包的路径。参数是array,可以是相对目录也可以是绝对目录。默认是 [path.resolve(process.cwd(),'node_modules')]。当前命令的目录下面的node_modules文件夹。

    如果一个大的项目里面有很多子项目,每个子项目没必要都安装依赖包,所以可以在各个子项目里面通过配置resolve.modules指向母项目的node_modules包。

  • 自定义引入模块时可以不带扩展名。参数是array。默认['.js','.json']

    extensions:['.js','.vue','.json','.css','.less'],复制代码

    代码里面

    import 'view/dom'复制代码

    会自动找到dom.js

  • 自定义路径别名。参数是object。

    alias:{    '@': path.resolve(__dirname, './src')},// __dirname 当前文件的目录地址。复制代码

    在代码里可以使用@符号指向src目录。

    import '@/view/dom.js';复制代码

    好处:在很深的代码层里面如果想引入顶层的某个js文件。不需要写很多'../../../'去找文件,提高开发效率。

resolve里面有很多的自定义解析规则。有时间都可以尝试一下。

四、生产与开发环境分开打包

代码内容详见

虽然在webpack4里面提供了mode属性来分别打包开发和生产环境,各自提供不同的插件。但是如果clean-webpack-plugin插件想在生产环境使用在开发环境不使用,就需要每次手动更改配置,这样做很不合理,容易出错。
可以使用

  • 指定配置文件。
    webpack --config 配置文件复制代码
  • 合并公共的配置

具体操作

新增依赖包

npm i webpack-merge -D复制代码

新增文件

新建build文件夹

mkdir build cd build touch weboack.build.conf.js、webpack.base.conf.js、webpack.dev.conf.js config.js help.js复制代码

help.js 储层公共方法

var path = require('path');module.exports.getMode = function() {  return process.env.NODE_ENV === 'development'?'development':'production'};module.exports.resolve = function(p){  return path.resolve(process.cwd(),p);}复制代码

config.js 开发与生产的配置信息

module.exports = {  dev: {    mode: 'development',    publicPath: '/',    devServer: {      port: '8899',      proxy: {        '/test/shortRent': {          target: 'http:"//www.baidu.com',          changeOrigin: true,          pathRewrite: {            '^/test/shortRent': '/evcard-evrental'          }        },      },    },  },  build: {    mode: 'production',    publicPath: './',    assetsRoot: 'you-app'  }}复制代码

webpack.base.conf.js 开发与生产相同的webpack配置

var path = require('path');var help = require('./help.js');var config = require('./config.js');var htmlWebpackPlugin = require('html-webpack-plugin');var mode = help.getMode();module.exports={  entry:{    app:help.resolve('./app.js')  },  output:{  },  resolve:{ // 解析    alias:{      '@': help.resolve('./src')    },    extensions:['.js','.vue','.json','.css','.less'],    modules: ["./node_modules"]  },  externals:{ //外部扩展    'Vue':'window.Vue'  },  plugins:[    new htmlWebpackPlugin({      filename:'index.html',      template:'./index.html',      inject:true,    })  ],}复制代码

webpack.dev.conf.js 开发环境的webpack配置

var merge = require("webpack-merge");var webpackConfigBase = require('./webpack.base.conf');var help = require('./help.js');var config = require('./config.js');module.exports=merge(webpackConfigBase,{  mode: config.dev.mode,  output:{    filename:help.assetsPath('js/[name].js'),    publicPath:config.dev.publicPath  },  devServer:config.dev.devServer})复制代码

webpack.build.conf.js 生产环境的webpack配置

var cleanWebpackPlugin = require('clean-webpack-plugin');var merge = require("webpack-merge");var help = require('./help.js');var webpackConfigBase = require('./webpack.base.conf.js');var config = require('./config.js');module.exports=merge(webpackConfigBase,{  mode: config.build.mode,  output:{    filename:'assets/js/[name].[hash].js',    publicPath:config.build.publicPath,    path:help.resolve(config.build.assetsRoot),  },  plugins:[    new cleanWebpackPlugin()  ]})复制代码

命令修改

"scripts": {    "build": "cross-env NODE_ENV=production webpack --config build/weboack.build.conf.js",    "dev": "cross-env NODE_ENV=development webpack-dev-server --config build/webpack.dev.conf.js"  },复制代码

五、解析转译JS

代码内容详见

loaders

用来解析文件转译成浏览器可以识别的文件。如.less、.vue、.jsx等这些文件浏览器是不能正常转译的,loaders的作用就是充当着'翻译'的作用。

babel-loader

我们在开发的时候都使用es6的语法去编写代码,但是有些浏览器不支持es6的代码就需要将es6转译成浏览器可以读懂的es5的代码。的作用就是'翻译'es6代码。

基础配置

安装babel-loader。参照官方的安装方式,打开选择webpack的安装方式。

安装依赖

npm install --save-dev babel-loader @babel/corenpm install @babel/preset-env --save-dev复制代码

babel-loader @babel/core 是核心插件

编译方式

配置规则

module: {  rules: [        {            test: /\.js$/,  // 正则匹配,所有的.js文件都使用这个规则进行编译            exclude: /node_modules/, // 排除的文件夹。这个文件夹里面的的文件不进行转译            loader: "babel-loader", // 转译的插件            options: {  // 转译的规则                presets: [ //转译器配置                    [                        "@babel/preset-env"                    ]                ],                plugins: [] // 转译插件配置            }        },  ]}复制代码

plugins(转译插件)。转译插件是用来转译单一功能的插件,比如transform-es2015-arrow-functions,这个插件只负责转译es2015新增的箭头函数。

presets(转译器)。转译器是一系列转译插件的集合。比如babel-preset-es2015就包含了es2015新增语法的所有转译插件,比如包含transform-es2015-arrow-functions(es2015箭头函数转译插件)、transform-es2015-classes(es2015 class类转译插件)等。转译器分为语法转译器和补丁转译器。

在app.js里面写es6的代码

const s = new Set([1, 2, 3, 4, 5, 3, 2, 16, 7, 83, 21, 2, 1]);var w = Object.assign({}, { w: 1, e: 4 })console.log(w);console.log([...s]);function pro(v) {  return new Promise((resolve) => {    if (v) {      resolve('真11')    } else {      resolve('假22')    }  })}pro(true).then(res=>{  console.log(res)})复制代码

运行命令

npm run build复制代码

打开打包后的app.js只有1.7kb。

promise里面的箭头函数已经被转译成了普通函数。
似乎看起来已经已经成功了。

npm run dev复制代码

在打包后的js全局搜索
promose,代码里面只有一处。没有其他的代码来'翻译'
promise,这在低版本的浏览器里面是不行的,所以需要继续'翻译'。

垫片配置

Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API,比如 Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise 等全局对象,以及一些定义在全局对象上的方法(比如 Object.assign)都不会转码。

所以还需要配置。 在babel@7.4以前使用为当前环境提供一个垫片。所谓垫片也就是垫平不同浏览器或者不同环境下的差异。

但是babel@7.4及以后这个垫片被废弃了。

babel-polyfill 等同于 regenerator runtime + core-js
官方建议使用

import "core-js/stable";import "regenerator-runtime/runtime";复制代码

来代替@babel/polyfill。

  • regenerator:提供对 generator 支持,如果应用代码中用到generator、async函数的话。
  • core-js:提供 es(6-8) 新的特性。

core-js 在安装@babel/preset-env的时候已经安装好了。

npm i regenerator-runtime -D复制代码

在app.js里面引入

import "core-js/stable";import "regenerator-runtime/runtime";复制代码

运行命令

npm run build复制代码

打包后的app.js有113kb。多出来了100多kb的代码。
打开打包后的js,搜索
promise

一共有26处,这里面对promise的代码进行了'翻译'。
但代码相比以前也太大了。把所有转译es的代码都打包了。

优化

这个配置属性可以解决这个问题。官方文档的配置其实是babel@7.4以前的写法,这也造成了我懵逼了两天。

属性值 "usage" | "entry" | false, 默认是 false。

useBuiltIns: 'entry' 其实和import "core-js/stable"; import "regenerator-runtime/runtime";效果是一样的,表示把所有的转译代码都注入到打包的代码里面。但是还是需要在代码里面引入这两个插件。

useBuiltIns: 'usage' 表示把代码里面需要用到的转译代码注入到打包的代码里面。就不需要引入core-js/stable了。但是regenerator-runtime/runtime还是需要继续引入。

{    test: /\.js$/,  // 正则匹配,所有的.js文件都使用这个规则进行编译    exclude: /node_modules/, // 排除的文件夹。这个文件夹里面的的文件不进行转译    loader: "babel-loader", // 转译的插件    options: {  // 转译的规则        presets: [ //转译器配置            [                "@babel/preset-env", {                    useBuiltIns: "usage"                  }            ]        ],        plugins: [] // 转译插件配置    }},复制代码

运行打包命令

npm run build复制代码

打包报错了

根据 的文档说明还需要配置
corejs。作用是代替引入
core-js/stable

{    test: /\.js$/,  // 正则匹配,所有的.js文件都使用这个规则进行编译    exclude: /node_modules/, // 排除的文件夹。这个文件夹里面的的文件不进行转译    loader: "babel-loader", // 转译的插件    options: {  // 转译的规则        presets: [ //转译器配置            [                "@babel/preset-env", {                    useBuiltIns: "usage",                    corejs: 3                  }            ]        ],        plugins: [] // 转译插件配置    }},复制代码

运行打包命令

npm run build复制代码

只有33kb。

打包的文件中有21个promise。

这样做的好处就是使用哪种es语法就引入哪种转译器,避免代码过大。为什么还需要继续引入regenerator-runtime/runtime呢?因为它的代码太少了,@babel/preset-env没有像corejs一样进行配置。如果不引入async、await就不能使用了。

更优秀的解决方案

动态 polyfill

是动态polyfill解决方案最好的方法。

用最新的Chrome打开

它会根据你的浏览器 UA 头,判断你是否支持某些特性,从而返回给你一个合适的 polyfill。对于最新的 Chrome 浏览器来说,不需要任何polyfill,所以返回的内容为空。

实验

去除useBuiltIns配置

app.js去除core-js/stable,保留"regenerator-runtime/runtime" 因为async、await需要。
页面引入polyfill.io

复制代码

模拟ie7浏览器。

页面加载正常。polyfill.min.js 引入了很多的js代码。里面有很多的es5转译方法。
模拟safari@12.1

页面加载正常。没有一行es5转译方法。

后面我又用vivo Y13手机, 14年的安卓4.2.2手机测试了一下。是可以用的,es7、es6都可以正常运行。

总结

对于最新的 safari 浏览器来说,不需要任何 polyfill,所以返回的内容为空。对于 iie7浏览器 来说,需要 URL 对象的 polyfill,所以返回了对应的资源。

babel-loader还有很多配置很多坑,遇到就查文档或者google吧。

六、样式loader与样式HMR

代码内容详见

样式loader

,这些都是官方提供的样式loader。

  • style-loader 将js里面引入的css文件,解析成css样式并且添加到style标签里面。
  • css-loader 解析css里面的@import引入的样式。
  • less-loader sass-loader stylus-loader 都是解析css扩展语言。
  • postcss-loader 为css3的代码自动添加前缀。

基础配置

比如 使用less作为样式语法。 首先安装style-loader css-loader。

npm i style-loader css-loader -D复制代码

文档里面显示需要安装

npm install --save-dev less-loader less复制代码

按照官方的配置进行rules配置。
编写base.less文件

body{  color: lawngreen;}.logo{  background: #f60;  height: 400px;  width: 400px;  background-repeat: no-repeat;  transition: all 1s;  display: flex;}.logo:hover{  height: 600px;  width: 600px;  transform: translateY(60px);}复制代码

在app.js 里面引入

import './src/assets/css/base.less';复制代码

运行命令

npm run dev复制代码

自动添加css3浏览器前缀

less文件里面的transition和transform都是css3的样式,如果想自动的生成带前缀的代码则需要,也需要postcss-loader的一个插件

安装依赖

npm i autoprefixer postcss-loader -D复制代码

更改配置

{            loader: "postcss-loader",            options: {                plugins: [                    require("autoprefixer")({                        browsers: [                            'last 10 Chrome versions',                            'last 5 Firefox versions',                            'Safari >= 6',                            'ie> 8'                        ]                    })                ]            }        },复制代码

browsers配置表示按照 大于ie8,Safari6,最后10个Chrome版本的规则进行编译。

npm run dev复制代码

css3的代码都进行了前缀编码。

importLoaders

home.less里面的代码并没有进行css3的转化。这时我们需要配置在 css-loader 中使用 属性。

将importLoaders设置为2因为,css-loader前面需要执行postcss-loader和less-loader。

生产环境配置

之前一直运行的是开发环境,我们运行一下生产打包命令

npm run build复制代码

打包后并没有css文件。 把代码放入服务器或者使用起一个本地的服务器。

这时我们需要引入进行css代码的抽离,以及打包插件在打包的时候进行css代码压缩。

npm i mini-css-extract-plugin optimize-css-assets-webpack-plugin -D复制代码

按照官方的语法进行配置

npm run build复制代码

css的代码已经被抽离了并且压缩了。

样式HMR

查看官网有关于解释。

模块热替换(HMR - Hot Module Replacement)功能会在应用程序运行过程中替换、添加或删除模块,而无需重新加载整个页面。

按照官方的。 首先更改devServer的配置,设置属性为true。

因为设置模块热加载是开发环境需要的。所以更改webpack.dev.conf.js的配置。

plugins:[    new webpack.HotModuleReplacementPlugin()  ]复制代码

由于mini-css-extract-plugin不支持HMR,所以在开发环境继续使用style-loader。 现在css的HMR已经配置好了。

文件解析。

代码内容详见

文件解析需要用到的。

使用 作为文件解析的loader。 是一种'搬运工'的loader,将代码中需要的文件'搬运'到合适的地方,
url-loader在搬运的基础上可以在代码上添加数据的作用,如添加base64的图片。

{	test: /\.(png|jpg|gif)$/,	use: [{		// 需要下载file-loader和url-loader		loader: "url-loader",		options: {			limit: 5 * 1024, //小于5kb将会已base64位图片打包处理 			// 图片文件输出的文件夹			outputPath: help.assetsPath("images"),			name: '[name].[ext]'		}	}]},{	test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,	loader: 'url-loader',	options: {		limit: 10000,		outputPath: help.assetsPath("fonts")	}},复制代码

转载地址:http://qlxro.baihongyu.com/

你可能感兴趣的文章
hive-site.xml配置文件参数解释.docx
查看>>
linux基础入门--文件管理命令
查看>>
众擎易举,全力打造企业护卫舰——高可用性体系(下)
查看>>
关于Cookie中的Path和domain
查看>>
DBUtils工具笔记【简】
查看>>
linux特殊权限
查看>>
针对url参数的加密解密算法(原创)
查看>>
Bootstrap中nav在container中用affix时,nav宽度撑不满容器的解决方案
查看>>
VC6.0 + WDK 7600.16385.1 开发环境配置
查看>>
windows下Apache 内存耗尽假死显现
查看>>
OFBiz + Opentaps 目录管理 四. 产品(三)数字产品
查看>>
Oracle SCN详解
查看>>
npm安装package.json中的模块依赖
查看>>
maven学习笔记一(认识maven)
查看>>
phpenv 部署
查看>>
mysql分库分表总结
查看>>
注册JDBC的三种方式
查看>>
如何基于 PHP-X 快速开发一个 PHP 扩展
查看>>
vbs
查看>>
(转)REST反模式
查看>>