视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
使用webpack构建应用的方法步骤
2020-11-27 22:00:27 责编:小采
文档

如何使用webpack

npm init -y
npm install webapck webpack-cli --save-dev
touch webpack.config.js

在webpack.config.js中下面添加内容

const path = require('path');

module.exports = {
 entry: './src/index.js',
 output: {
 filename: 'main.js',
 path: path.resolve(__dirname, 'dist')
 }
};

  • entry:工程资源的入口,可以是单个文件,也可以是多个文件,通过每一个资源入口,webpack会一次去寻找它的依赖进行模块打包。我们可以把entry理解为整个依赖树的根,每个入口都将对应一个最终生成的打包结果。
  • output:这是一个配置对象,通过它我们可以对最终打包的产物进行配置,这里配置了两个属性,:
  • path:打包资源放置的路劲,必须为绝对路径。
  • filename:打包结果的文件名。
  • 定义好配置文件后,用npx webpack或者./node_modules/.bin/webpack执行

    使用loader

    项目中需要引入一个css文件,如果直接用webpack去执行就会报错,需要再webpack中加入loader机制

    module.exports = {
     ...
     module: {
     rules: [
     {
     // 用正则去匹配 .css 结尾的文件,然后需要使用 loader 进行转换
     test: /\.css$/,
     use: ['style-loader', 'css-loader']
     }
     ]
     }
    }
    

    编译之前还需要安装style-loader和css-loader

    npm install --save-dev style-loader css-laoder

    注意:

    use属性的值是一个使用loader名称组成的数组,loader执行的顺序是从后往前的,由于loader执行有顺序,故不能写成这样

    use: ['css-loader', 'style-loader']

    每个loader都可以通过URL queryString的方式传入参数,比如'css-loader?url'

    style-loader的原理:是将css的内容使用javascript的字符串存储起来,在网页执行javascript时通过DOM操作,动态地向HTML head标签里插入HTML style标签。

    配置loader的方式也可以用Object来实现

    use: ['style-loader', {
     loader: 'css-loader',
     options: {
     url: true
     }
    }]
    

    使用plugin

    loader的作用是被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务,插件的范围包括,从打包优化和压缩,一直到重新定义环节中的变量。

    如果想要使用一个插件,我们只需要require()它,然后把它添加到plugins数组中。我们可以在一个配置文件中因为不同的目的多次使用用一个插件,因此我们可以使用new操作符来创建它的实列。

    上面使用loader把css加载到js中去,现在使用extract-text-webpack-plugin插件把bundle.js文件里的css提取到单独的文件中

    // 提取 css 的插件
    const ExtractTextPlugin = require('extract-text-webpack-plugin')
    
    module: {
     rules: [
     {
     // 用正则去匹配 .css 结尾的文件,然后需要使用 loader 进行转换
     test: /\.css$/,
     loaders: ExtractTextPlugin.extract({
     //转换 .css需要使用的 loader
     use: ['css-loader']
     })
     }
     ]
    },
    plugins: [
     //从 js 文件中提取出来的 .css 文件名称
     new ExtractTextPlugin({
     filename: 'main.css'
     })
    ]
    
    

    编译之前需要安装extract-text-webpack-plugin

    npm install --save-dev extract-text-webpack-plugin
    

    执行webpack时报错需要这样安装

    npm install extract-text-webpack-plugin@next

    DevServer

    官方网站

    安装

    npm install webpack-dev-server --save-dev

    然后进行简单的配置

    devServer:{
     port: 3000,
     publicPath: "/dist"
    }
    

    然后用./node_modules/.bin/webpack-dev-server执行

    资源压缩

    npm i uglifyJSPlugin-webpack-plugin --save-dev

    配置文件

    const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
    plugins: [
     new UglifyJSPlugin({
     //默认是 false 需要手动开启
     parallel: true
     })
    ]
    
    

    或者

    optimization: {
     minimizer: [new UglifyJsPlugin()],
    },
    

    按需加载

    在代码层面,webpack支持两种方式进行异步模块加载,一种是CommonJS形式的require.ensure,一种是ES6 Module形式的异步import()

    异步加载的脚本不允许使用document.write,所以将module.js的代码改成console.log

    export const log = function(){
     console.log('module.js loaded.')
    }
    

    编辑app.js,将module.js以异步的形式加载进来

    import('./module.js').then(module =>{
     module.log()
    }).catch(error => "An error occurred while loading the module")
    document.write('app.js loaded.')
    

    修改配置

    module.exports = {
     mode: "production",
     entry: './app.js',
     output: {
     filename: 'main.js',
     path: path.resolve(__dirname, 'dist'),
     publicPath: "./dist"
     },
    }
    

    这里我们在output中添加了一个配置项publicPath,它是webpack中一个很重要有很容易引起迷惑的配置,当我们的工程中有按需加载以及图片和文件等外部资源时,就需要它来配置这些资源的路径,否则页面上就会报404,这里我们将publicPath配置为相对于html的路径,使按需加载的资源生产在dist目录下,并且能正确地引用到它。

    重新打包之后你会发现打包结果中多出一个1.mian.js,这里面就是将来会被异步加载进来的内容。刷新页面并查看chrome的network标签,可以看到页面会请求1.main.js。它并不来源于index.html中的引用,而是通过main.js在页面插入了script标签来将其引入的。

    使用webpack的构建特性

    从2.0.0版本开始,webpack开始加入了更多的可以优化构建过程的特性。

    tree-shaking

    在关于模块的那一篇文章中我们提到过,ES6 Module的模块依赖解析是在代码静态分析过程中进行的。换句话说,它可以在代码的编译过程中得到依赖树,而非运行时。利用这一点webpack提供tree-shaking功能,它可以帮助我们检测工程中哪些模块有从未被引用到的代码,这些代码不可能被执行到,因此也称为“死代码”。通过tree-shaking,webpack可以在打包过程中去掉这些死代码来减小最终的资源体积。

    开启tree-shaking特性很简单,只要保证模块遵循ES6 Module的形式定义即可,这意味着之前所有我们的例子其实都是默认已经开启了的。但是要注意如果在配置中使用了babel-preset-es2015或者babel-preset-env,则需要将其模块依赖解析的特性关掉,如:

    presets: [
     [env, {module: false}]
    ] 
    

    这里我们测试一下tree-shaking的功能,编辑module.js:

    // module.js 
    export const log = function() { 
     console.log('module.js loaded.'); 
    } 
    
    export const unusedFunc = function() { 
     console.log('not used'); 
    } 
    
    

    打开页面查看1.main.js的内容,应该可以发现unusedFunc的代码是不存在的,因为它没有被别的模块使用,属于死代码,在tree-shaking的过程中被优化掉了。

    tree-shaking最终的效果依赖于实际工程的代码本身,在我对于实际工程的测试中,一般可以将最终的体积减小3%~5%。总体来看,我认为如果要使tree-shaking发挥真正的效果还要等几年的时间,因为现在大多数的npm模块还是在使用CommonJS,因此享受不了这个特性带来的优势。

    scope-hoisting

    scope-hoisting(作用域提升)是由webpack3提供的特性。在大型的工程中模块引用的层级往往较深,这会产生比较长的引用链。scope-hoisting可以将这种纵深的引用链拍平,使得模块本身和其引用的其它模块作用域处于同级。这样的话可以去掉一部分 webpack的附加代码,减小资源体积,同时可以提升代码的执行效率。

    目前如果要开启scope-hoisting,需要引入它的一个内部插件:

    module.exports = { 
     plugins: [ 
     new webpack.optimize.ModuleConcatenationPlugin() 
     ] 
    }
    

    scope-hoisting生效后会在bundle.js中看到类似下面的内容,你会发现log 的定义和调用是在同一个作用域下了:

    // CONCATENATED MODULE: ./module.js 
    const log = function() { 
     console.log('module.js loaded.'); 
    } 
    
    // CONCATENATED MODULE: ./app.js 
    log();
    
    

    下载本文
    显示全文
    专题