webpack——快速入门【一】

学习webpack

https://github.com/webproblem/learning-article#webpack

https://github.com/lengziyu/learn-webpack

先跟着下面这个例子来做一遍,因为版本原因如果你跟着原文可能会出错,所以我会在这里修复原文中的错误,本文使用的是4.29.3版本

https://segmentfault.com/a/1190000006178770?utm_source=tag-newest

请结合官方文档来进行学习

https://www.webpackjs.com/concepts/#%E5%85%A5%E5%8F%A3-entry-

https://webpack.js.org/configuration/dev-server#devserver

什么是webpack

webpack 是一个现代 JavaScript 应用程序的静态模块打包器(module bundler)。当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle

为什么使用webpack

① 模块化开发(import,require)
② 预处理(Less,Sass,ES6,TypeScript……)
③ 主流框架脚手架支持(Vue,React,Angular)
④ 庞大的社区(资源丰富,降低学习成本)

总之一句话,方便快捷便于我们快速的开发。

快速开始

根据整理的资料进行实际操作,并修正版本更新造成一些命令引发的错误,我用的工具是gitbash,平台为windows平台,安装都只是安装到项目文件夹中没有进行全局安装

创建空文件夹

$ mkdir webpack

$ cd webpack

$ mkdir {app,public}

$ ll
total 0
drwxr-xr-x 1 Administrator 197121 0 二月 13 13:23 app/
drwxr-xr-x 1 Administrator 197121 0 二月 13 13:23 public/

安装webpack

进入文件根目录,然后安装webpack到此项目中,这个用的是淘宝镜像,这样可以加快安装速度。

npm指向淘宝镜像

$ cnpm install --save-dev webpack
platform unsupported [email protected][email protected][email protected] › fsevents@^1.2.7 Package require os(darwin) not compatible with your platform(win32)
[fsevents@^1.2.7] optional install error: Package require os(darwin) not compatible with your platform(win32)
√ Installed 1 packages
√ Linked 267 latest versions √ Run 0 scripts Recently updated (since 2019-02-06): 6 packages (detail see file C:\Users\Administrator.KING\Desktop\webpack\node_modules\.recently_updates.txt) √ All packages installed (292 packages installed from npm registry, used 5s(network 5s), speed 100.79kB/s, json 268(498kB), tarball 0B)

创建文件

cd到app文件夹下创建greeter.js和main.js

$ cd app

$ vi greeter.js

$ vi main.js

greeter.js

Greeter.js中定义一个返回包含问候信息的html元素的函数,并依据CommonJS规范导出这个函数为一个模块

module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = "小哥哥,快来啊,快活啊";
  return greet;
};

main.js

main.js文件中我们写入下述代码,用以把Greeter模块返回的节点插入页面。

const greeter = require('./Greeter.js');
document.querySelector("#root").appendChild(greeter());

cd到public下面创建index.html

$ cd ..

$ cd public/
$ vi index.html

index.html

其中bundle.js为打包后的js文件名称

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Webpack Sample Project</title>
  </head>
  <body>
    <div id='root'>
    </div>
    <script src="bundle.js"></script>
  </body>
</html>

打包

这里安装使用的就是非全局安装,所以打包也使用非全局打包

$ node_modules/.bin/webpack app/main.js -o public/bundle.js
Hash: c6d5fc7966695da6f6cd
Version: webpack 4.29.3
Time: 358ms
Built at: 2019-02-13 12:54:49
Asset Size Chunks Chunk Names
bundle.js 1.09 KiB 0 [emitted] main
Entrypoint main = bundle.js
[0] ./app/main.js 255 bytes {0} [built]
[1] ./app/Greeter.js 304 bytes {0} [built]

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

进入public打开index.html即可查看效果

创建配置文件

在根目录下创建webpack.config.js文件,主要配置入口文件和打包后文件

module.exports = {
  entry:  __dirname + "/app/main.js",//已多次提及的唯一入口文件
  output: {
    path: __dirname + "/public",//打包后的文件存放的地方
    filename: "bundle.js"//打包后输出文件的文件名
  }
}

:“__dirname”是node.js中的一个全局变量,它指向当前执行脚本所在的目录。

修改greeter.js重新打包

就是改了下文字内容~

module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = "We still hava a long way to go.";
  return greet;
};

重新打包

这时候就很简单了,当然如果全局安装的话,直接webpack就可以了

$ node_modules/.bin/webpack
Hash: 9725aade1d1273904ee2
Version: webpack 4.29.3
Time: 364ms
Built at: 2019-02-13 14:19:38
    Asset     Size  Chunks             Chunk Names
bundle.js  1.1 KiB       0  [emitted]  main
Entrypoint main = bundle.js
[0] ./app/main.js 255 bytes {0} [built]
[1] ./app/Greeter.js 314 bytes {0} [built]

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

自定义打包命令

npm进行配置后可以在命令行中使用简单的npm start命令来替代上面略微繁琐的命令。在package.json中对scripts对象进行相关设置

如果没有这个package.json文件不要慌,直接npm init初始化一个就可以了,现在开始配置。

反正是测试不发布的,所以可以直接回车即可。

$ npm init

打开package.json修改scripts对象添加以下内容

我这里是非全局安装所有添加的是node_modules/.bin/webpack,全局安装的直接添加webpack即可

"start":"node_modules/.bin/webpack"  

完整的json文件如下

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "dependencies": {
    "webpack-cli": "^3.2.3",
    "webpack": "^4.29.3"
  },
  "devDependencies": {},
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start":"node_modules/.bin/webpack"  
  },
  "author": "",
  "license": "ISC"
}

再次修改greeter.js

module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = "Hello world";
  return greet;
};

使用自定义的命令打包

$ npm start

> webpack@1.0.0 start D:\wamp\www\webpack
> webpack

Hash: 1b28a19fd8d2277de6f0
Version: webpack 4.29.3
Time: 376ms
Built at: 2019-02-13 14:31:57
    Asset      Size  Chunks             Chunk Names
bundle.js  1.08 KiB       0  [emitted]  main
Entrypoint main = bundle.js
[0] ./app/main.js 255 bytes {0} [built]
[1] ./app/Greeter.js 294 bytes {0} [built]

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

其中有个关于npm的小知识,需要各位到原文去查看,毕竟我们也是从人家那边学习,不给赞赏给给访问也可以啊

生成Source Maps

webpack的配置文件中配置source maps,需要配置devtool,它有以下四种不同的配置选项,各具优缺点,描述如下:

devtool选项 配置结果
source-map 在一个单独的文件中产生一个完整且功能完全的文件。这个文件具有最好的source map,但是它会减慢打包速度;
cheap-module-source-map 在一个单独的文件中生成一个不带列映射的map,不带列映射提高了打包速度,但是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试造成不便;
eval-source-map 使用eval打包源文件模块,在同一个文件中生成干净的完整的source map。这个选项可以在不影响构建速度的前提下生成完整的sourcemap,但是对打包后输出的JS文件的执行具有性能和安全的隐患。在开发阶段这是一个非常好的选项,在生产阶段则一定不要启用这个选项;
cheap-module-eval-source-map 这是在打包文件时最快的生成source map的方法,生成的Source Map 会和打包后的JavaScript文件同行显示,没有列映射,和eval-source-map选项具有相似的缺点;

上述选项由上到下打包速度越来越快,不过同时也具有越来越多的负面作用,较快的打包速度的后果就是对打包后的文件的的执行有一定影响。

对小到中型的项目中,eval-source-map是一个很好的选项,再次强调你只应该开发阶段使用它,我们继续对上文新建的webpack.config.js,进行如下配置:

module.exports = {
    devtool: 'eval-source-map',
    entry: __dirname + "/app/main.js",
    output: {
        path: __dirname + "/public",
        filename: "bundle.js"
    }
}

可能有的同学一直看到了这个警告

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/

这是什么呢,因为我们没有在webpack.config.js中配置模式造成了,我们顺手也配置下吧

development 开发环境
production  生产环境
module.exports = {
    mode:'development',
    devtool: 'eval-source-map',
    entry: __dirname + "/app/main.js",
    output: {
        path: __dirname + "/public",
        filename: "bundle.js"
    }
}

构建本地服务器

可以让浏览器监听你的代码的修改,并自动刷新显示修改后的结果

$ cnpm install --save-dev webpack-dev-server
platform unsupported webpack-dev-server@3.1.14 › chokidar@2.1.1 › fsevents@^1.2.7 Package require os(darwin) not compatible with your platform(win32)
[fsevents@^1.2.7] optional install error: Package require os(darwin) not compatible with your platform(win32)
√ Installed 1 packages
√ Linked 429 latest versions
√ Run 0 scripts
Recently updated (since 2019-02-06): 7 packages (detail see file D:\wamp\www\webpack\node_modules\.recently_updates.txt)
√ All packages installed (472 packages installed from npm registry, used 19s(network 19s), speed 43.94kB/s, json 430(799.49kB), tarball 36.44kB)

修改配置文件webpack.config.js

module.exports = {
    mode:'development',
    devtool: 'eval-source-map',
    entry: __dirname + "/app/main.js",
    output: {
        path: __dirname + "/public",
        filename: "bundle.js"
    },
    devServer: {
        contentBase: "./public",//本地服务器所加载的页面所在的目录
        historyApiFallback: true,//不跳转
        inline: true//实时刷新
  }
}

package.json中的scripts对象中添加如下命令,用以开启本地服务器:

{
  "name": "webpack",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "dependencies": {
    "webpack-cli": "^3.2.3",
    "webpack": "^4.29.3"
  },
  "devDependencies": {
    "webpack-dev-server": "^3.1.14"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node_modules/.bin/webpack",
    "server": "webpack-dev-server --open"
  },
  "author": "",
  "license": "ISC"
}

运行服务

$ npm run server

> webpack@1.0.0 server D:\wamp\www\webpack
> webpack-dev-server --open

i 「wds」: Project is running at http://localhost:8081/
i 「wds」: webpack output is served from /
i 「wds」: Content not from webpack is served from ./public
i 「wds」: 404s will fallback to /index.html
i 「wdm」: wait until bundle finished: /
i 「wdm」: Hash: a3f5179d4ce1ace1f048
Version: webpack 4.29.3
Time: 744ms
Built at: 2019-02-13 14:56:40
    Asset     Size  Chunks             Chunk Names
bundle.js  867 KiB    main  [emitted]  main
Entrypoint main = bundle.js
[0] multi ./node_modules/_webpack-dev-server@3.1.14@webpack-dev-server/client?http://localhost:8081 ./app/main.js 40 bytes {main} [built]
[./app/Greeter.js] 294 bytes {main} [built]
[./app/main.js] 255 bytes {main} [built]
[./node_modules/_ansi-html@0.0.7@ansi-html/index.js] 4.16 KiB {main} [built]
[./node_modules/_ansi-regex@2.1.1@ansi-regex/index.js] 135 bytes {main} [built]
[./node_modules/_html-entities@1.2.1@html-entities/index.js] 231 bytes {main} [built]
[./node_modules/_loglevel@1.6.1@loglevel/lib/loglevel.js] 7.68 KiB {main} [built]
[./node_modules/_sockjs-client@1.3.0@sockjs-client/dist/sockjs.js] 180 KiB {main} [built]
[./node_modules/_strip-ansi@3.0.1@strip-ansi/index.js] 161 bytes {main} [built]
[./node_modules/_webpack-dev-server@3.1.14@webpack-dev-server/client/index.js?http://localhost:8081] ./node_modules/[email protected]@webpack-dev-server/client?http://localhost:8081 7.78 KiB {main} [built]
[./node_modules/_webpack-dev-server@3.1.14@webpack-dev-server/client/overlay.js] 3.58 KiB {main} [built]
[./node_modules/_webpack-dev-server@3.1.14@webpack-dev-server/client/socket.js] 1.05 KiB {main} [built]
[./node_modules/url/url.js] 22.8 KiB {main} [built]
[./node_modules/webpack/hot sync ^\.\/log$] (webpack)/hot sync nonrecursive ^\.\/log$ 170 bytes {main} [built]
[./node_modules/webpack/hot/emitter.js] (webpack)/hot/emitter.js 75 bytes {main} [built]
    + 12 hidden modules
i 「wdm」: Compiled successfully.

Loader

配置loader之前,我们把Greeter.js里的问候消息放在一个单独的JSON文件里,并通过合适的配置使Greeter.js可以读取该JSON文件的值,各文件修改后的代码如下:

在app文件夹下新增一个greet.json文件

greet.json

{
  "greetText": "Hi there and greetings from JSON!"
}

greeter.js

var config = require('./greet.json');
module.exports = function() {
  var greet = document.createElement('div');
  greet.textContent = config.greetText;;
  return greet;
};

自动编译的结果显示

Babel

Babel其实是一个编译JavaScript的平台,它可以编译代码帮你达到以下目的:

  • 让你能使用最新的JavaScript代码(ES6,ES7...),而不用管新标准是否被当前使用的浏览器完全支持;
  • 让你能使用基于JavaScript进行了拓展的语言,比如React的JSX;

安装依赖包

新版本的要求依赖包必须是7的,不然是会报错的,报错不可怕,只要看信息总会解决的!

$ cnpm install --save-dev babel-core babel-loader@7  babel-preset-env babel-preset-react

√ Installed 4 packages
√ Linked 121 latest versions
√ Run 0 scripts
peerDependencies WARNING babel-loader@* requires a peer of @babel/core@^7.0.0 but none was installed
Recently updated (since 2019-02-06): 3 packages (detail see file D:\wamp\www\webpack\node_modules\.recently_updates.txt)
√ All packages installed (113 packages installed from npm registry, used 4s(network 4s), speed 329.85kB/s, json 125(427.86kB), tarball 873.08kB)

配置webpack.config.js文件

module.exports = {
    mode: 'development',
    devtool: 'eval-source-map',
    entry: __dirname + "/app/main.js",
    output: {
        path: __dirname + "/public",
        filename: "bundle.js"
    },
    devServer: {
        contentBase: "./public",
        historyApiFallback: true,
        inline: true
    },
    module: {
        rules: [{
            test: /(\.jsx|\.js)$/,
            use: {
                loader: "babel-loader",
                options: {
                    presets: [
                        "env", "react"
                    ]
                }
            },
            exclude: /node_modules/
        }]
    }
}

现在你的webpack的配置已经允许你使用ES6以及JSX的语法了。继续用上面的例子进行测试,不过这次我们会使用React,记得先安装 React 和 React-DOM

我只想学下webpack你还给我赠送了react......

$ cnpm install --save react react-dom
√ Installed 2 packages
√ Linked 5 latest versions
√ Run 0 scripts
Recently updated (since 2019-02-06): 5 packages (detail see file D:\wamp\www\webpack\node_modules\.recently_updates.txt)
√ All packages installed (5 packages installed from npm registry, used 1s(network 1s), speed 901.37kB/s, json 7(32.33kB), tarball 1.21MB)

接下来我们使用ES6的语法,更新greeter.js并返回一个React组件

import React, {Component} from 'react'
import config from './config.json';

class Greeter extends Component{
  render() {
    return (
      <div>
        {config.greetText}
      </div>
    );
  }
}

export default Greeter

修改main.js如下,使用ES6的模块定义和渲染Greeter模块

import React from 'react';
import {render} from 'react-dom';
import Greeter from './greeter';

render(<Greeter />, document.getElementById('root'));

然后重新打包

$ npm start

> webpack@1.0.0 start D:\wamp\www\webpack
> webpack

Hash: bcd934684f9507b2fc78
Version: webpack 4.29.3
Time: 2240ms
Built at: 2019-02-13 16:13:51
    Asset      Size  Chunks             Chunk Names
bundle.js  2.16 MiB    main  [emitted]  main
Entrypoint main = bundle.js
[./app/Greeter.js] 5.28 KiB {main} [built]
[./app/greet.json] 58 bytes {main} [built]
[./app/main.js] 1.23 KiB {main} [built]
[./node_modules/webpack/buildin/global.js] (webpack)/buildin/global.js 472 bytes {main} [built]
    + 11 hidden modules

分开配置

 虽然可以在webpack.config.js中配置,但是babel的配置项还是很多的,所以我们单独命名一个.babelrc的配置文件

webpack会自动调用.babelrc的配置文件

webpack.config.js

module.exports = {
    mode: 'development',
    devtool: 'eval-source-map',
    entry: __dirname + "/app/main.js",
    output: {
        path: __dirname + "/public",
        filename: "bundle.js"
    },
    devServer: {
        contentBase: "./public",
        historyApiFallback: true,
        inline: true
    },
    module: {
        rules: [{
            test: /(\.jsx|\.js)$/,
            use: {
                loader: "babel-loader",
            },
            exclude: /node_modules/
        }]
    }
}

.babelrc

{
  "presets": ["react", "env"]
}

猜你喜欢

转载自www.cnblogs.com/wangyang0210/p/10371064.html