美文网首页
webpack v4 从dev到prd

webpack v4 从dev到prd

作者: 圆儿圈圈 | 来源:发表于2018-03-30 16:36 被阅读0次

    目录

    • 概述
    • Big changes
    • 加载loader方法总结
    • 开发必备的loader&plugins
    • 优化向prd进发
    • 未完待续

    概述

    本月迎来了 v4 正式版的发布,本文用于学习新特性和总结开发必用plugin & loader,从dev到prd,走你~

    Big changes

    • Environment
      • Node.js 4 is no longer supported. Source Code was upgraded to a higher ecmascript version.
    • Usage
      • You have to choose (mode or --mode) between two modes now: production or development

    本次新版本中引入了 mode 配置项,开发者可在 none,development(开发 ) 以及 production(产品)三种模式间选择。该配置项缺省情况下默认使用 production 模式。

    • development 模式给你极致的开发体验,包含浏览器调试相关工具,极快的增量编译,丰富全面的报错信息...
    • production 模式则包含大量发版优化,代码压缩,丝般润滑的运行时优化,开发相关代码的排除,易用,etc.
    • none 不使用预设,等于老版本中全部自己配置的原始状态。

    eg:

    webpack --mode development
    
    • Usage
      • Some Plugin options are now validated
      • CLI has been move to webpack-cli, you need to install webpack-cli to use the CLI
      • The ProgressPlugin (--progress) now displays plugin names
        At least for plugins migrated to the new plugin system

    新版中将 webpack 命令行工具拆分到单独的仓库中,所以需要额外安装 webpack-cli。

    npm init -y //初始化项目
    npm install webpack webpack-cli -D //安装webpack webpack-cli 依赖
    npx webpack --mode development // npx可以直接运行node_modules/.bin目录下面的命令
    
    或者通过配置package.json的script build
    "scripts": {
        "build": "webpack --mode development",
    },
    

    加载loader方法总结

    • use
    module: {
        rules:[
            { 
                test: /\.css$/,
                use: ['style-loader','css-loader']
            }
        ]
    }
    

    css-loader用来解析处理CSS文件中的url路径,

    要把CSS文件变成一个模块
    多个loader是有顺序要求的,从右往左写,因为转换的时候是从右往左转换

    此插件先用css-loader处理一下css文件,再用style-loader把CSS文件变成style标签插入head中

    • loader
    module: {
        rules:[
            {
                test: /\.css$/,
                loader: ["style-loader", "css-loader"]
            },
        ]
    }
    
    • use+loader
    module: {
        rules:[
            {
                test: /\.css$/,
                use:[
                    { loader:"style-loader"},
                    { 
                        loader: 'css-loader',
                        options: {sourceMap: true}
                    }
                ]
            }
        ]
    }
    

    这三种loader的写法,最后打包的结果相同

    loader中的options配置项可以用"?"跟在加载器后面

    eg:

    {  
        test: /\.jpeg$/,  
        use: 'url-loader?limit=1024&name=[path][name].[ext]&outputPath=img/&publicPath=output/',  
    }
    

    为以下配置的简写

    {  
        test: /\.jpeg$/,  
        use: {
            loader:'url-loader',
            options:{
                limit:1024,
                name:[path][name].[ext],
                outputPath:img/
                publicPath:output/'
            }
        }
    }
    

    开发必备的loader&plugins

    • css-loader
    • babel-loader

    讲ES6代码转换为ES5

    {
        test: /\.js/,
        use: {
            loader: 'babel-loader',
            query: {
                presets: ["env", "stage-0", "react"]
            }
        }
    },
    

    babel-loader的预设可以添加在query中,也可以在项目根目录添加 .babelrc 文件

    .babelrc

    {
        "presets": [
            "env",
            "stage-0",
            "react"
        ]
    }
    
    • html-webpack-plugin

    插件的基本作用就是生成html文件。原理很简单:

    将 webpack中entry配置的相关入口thunk 和 extract-text-webpack-plugin抽取的css样式 插入到该插件提供的template或者templateContent配置项指定的内容基础上生成一个html文件,具体插入方式是将样式link插入到head元素中,script插入到head或者body中。

    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
    new HtmlWebpackPlugin({
        template: './src/index.html',//指定产的HTML模板
        filename: `index.html`,//产出的HTML文件名
        title: 'index',
        hash: true,// 会在引入的js里加入查询字符串避免缓存,
        minify: {
            removeAttributeQuotes: true
        }
    }),
    

    可以用 cnpm search html-webpack-plugin 查找想用loader的用法

    • less-loader sass-loader

    优化向prd进发

    • 提取公共的css代码

    它会将所有的入口 chunk(entry chunks)中引用的 *.css,移动到独立分离的 CSS 文件。因此,你的样式将不再内嵌到 JS bundle 中,而是会放到一个单独的 CSS 文件(即 styles.css)当中。 如果你的样式文件大小较大,这会做更快提前加载,因为 CSS bundle 会跟 JS bundle 并行加载。

    npm i extract-text-webpack-plugin@next -D
    
    const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
    let cssExtract = new ExtractTextWebpackPlugin({
        filename: 'css/css.css',
        allChunks: true
    });
    
    module:{
        rules:[
            {
                test: /\.css$/,//转换文件的匹配正则
                loader: cssExtract.extract({
                    use: ["css-loader?minimize"]
                })
            },
        ]
    }
    plugins:[
        ...... ,
        + cssExtract
    ]
    
    • 尽量减少文件解析,用resolve配置文件解析路径,include
    rules: {
        test: /\.js$/,
        loader:'babel-loader',
        include: path.resolve(__dirname, 'src'),//只转换或者编译src 目录 下的文件
        exclude: /node_modules/ //不要解析node_modules
    }
    
    • resolve.mainFields
    WebpackTest
    |
    |
    | - src
    |   | - index.js
    |
    | - lib
    |   | - fetch
    |       |
    |       browser.js
    |       node.js
    |       package.json
    |
    | - webpack.config.js
    
    

    当从 npm 包中导入模块时(例如,引入lib下的库),此选项将决定在 package.json 中使用哪个字段导入模块。根据 webpack 配置中指定的 target 不同,默认值也会有所不同。

    package.json

    lib文件夹下的package.json中配置相对应模块的key

    {
      "name": "fetch",
      "version": "1.0.0",
      "description": "",
      "node": "./node.js",
      "browser": "./browser.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }
    

    webpack.config.js

    在resolve解析对象中,加入lib的路径

    resolve: {
        extensions: ['.js', '.json'],
        mainFields: ['main', 'browser', 'node'],
        modules: [path.resolve('node_modules'), path.resolve('lib')]
    }
    

    index.js

    这样在index.js中引用第三方库时,会去查找modules下的路径中是否配置了所需的文件,知道在package.json中找到mainFields中的key对应文件,停止。

    let fetch = require('fetch');
    console.log(fetch);
    

    打包后 console.log出的对象


    image

    如果交换mainFields中的key顺序

    mainFields: ['main', 'node','browser']
    

    打包后 console.log出的对象,因为找到了key=node对应的文件就停止了查找

    image
    • DllReferencePlugin

    这个插件是在 webpack 主配置文件中设置的, 这个插件把只有 dll 的 bundle(们)(dll-only-bundle(s)) 引用到需要的预编译的依赖。

    新建webpack.react.config.js

    const path = require('path');
    const webpack = require('webpack')
    module.exports = {
        entry: {
            react: ['react', 'react-dom']
        },
        output: {
            path: path.join(__dirname, 'dist'),// 输出动态连接库的文件名称
            filename: '[name]_dll.js',
            library: '_dll_[name]'//全局变量的名字,其它会从此变量上获取到里面的模块
        },
        // manifest 表示一个描述文件
        plugins: [
            new webpack.DllPlugin({
                name: '_dll_[name]',
                path: path.join(__dirname, 'dist', 'manifest.json')//最后打包出来的文件目录和名字
            })
        ]
    }
    
    在entry入口写入要打包成dll的文件,这里把体积较大的react和react-dom打包
    
    output中的关键是library的全局变量名,下文详细说明dll&manifest工作原理
    

    打包dll文件

    webpack --config webpack.react.config.js --mode development
    

    打包出来的manifest.json节选

    image

    打包出来的react_dll.js节选

    image

    可见manifest.json中的 name值就是

    output:{
        library:_dll_react
    }
    

    manifest.json就是借书证,_dll_react就像图书馆书籍的条形码,为我们最终找到filename为react_dll.js的参考书

    使用“参考书”

    在webpack.config.js中加入“借书证”

    new webpack.DllReferencePlugin({
        manifest: path.join(__dirname, 'dist', 'manifest.json')
    })
    

    再运行

    webpack --mode development
    

    打包速度显著变快


    image

    打包后的main.js中,react,react-dom.js也打包进来了,成功~

    import React from 'react';\n//import ReactDOM from 'react-dom';
    
     (function(module, exports, __webpack_require__) {
    
    "use strict";
    eval("\n\n//import name from './base';\n//import React from 'react';\n//import ReactDOM from 'react-dom';\n//import ajax from 'ajax';\n//let result = ajax('/ajax');\n\n//ReactDOM.render(<h1>{result}</h1>, document.getElementById('root'));\n// fetch fetch.js fetch.json fetch文件夹\n//let fetch = require('fetch');\n//console.log(fetch);\n//let get = require('../dist/bundle.js');\n//get.getName();\nconsole.log('hello');\n\nvar name = 'zfpx';\nconsole.log(name);\nif (true) {\n    var s = 'ssssssssssssssssssssssss';\n    console.log(s);\n    console.log(s);\n    console.log(s);\n    console.log(s);\n}\n\n//# sourceURL=webpack:///./src/index.js?");
    
    /***/ })
    
    /******/ });
    

    未完待续

    • webpack.ProvidePlugin
    • 拷贝静态资源
    • 压缩css(npm i -D purifycss-webpack purify-css)

    觉得好玩就关注一下欢迎大家收藏写评论~~

    相关文章

      网友评论

          本文标题:webpack v4 从dev到prd

          本文链接:https://www.haomeiwen.com/subject/krmicftx.html