webpack学习笔记: step2 进阶用法

几种基本用法

清理构建的目录

能够经过在执行构建的命令前加一句清除目录的命令
如在package.json里面的build命令修改成javascript

"scripts": {
    build: rm -rf ./dist && webpack
}

比较经常使用的是经过webpack的插件实现css

const { CleanWebpackPlugin }  = require('clean-webpack-plugin')
modules.export = {
    plugins: [
         new CleanWebpackPlugin()
    ]
}

处理样式

咱们须要添加css前缀来处理兼容性问题。经过配置postcss-loader来实现。注意是先添加前缀而后再把scss转换成css,因此要写在最下面。html

{
                test: /.scss$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'sass-loader',
                    {
                        loader: 'postcss-loader',
                        options: {
                            plugins: () => [
                                require('autoprefixer')({
                                    overrideBrowserslist: ['last 2 version', '>1%', 'ios 7']
                                })
                            ]
                        }
                    }
                ]
            },
modules.export = {
    plugins: [
        new OptimizeCssAssetsWebpackPlugin({
            assetNameRegExp: /\.css$/g,
            cssProcessor: require('cssnano')
        })
    ]
}

对于字体大小的兼容,咱们可使用rem做为字体的单位。可是把px转换成rem是一个比较麻烦的计算过程,并且须要对不一样分辨率下的设备,设置不一样的根元素字体大小,从而调整总体的字体大小。一个解决方案就是,在html页面引入flexible.js,再样式文件的loader里面添加px2rem-loader。
引入flexible.js,能够经过直接用script标签引入cdn的连接,也能够经过文件内联的形式,也就是把flexible.js里面的内容,直接嵌入到<script></script>中。这里只介绍内联方式。
因为咱们使用的是html-webpack-plugin把html模板编译到dist下面,因此是支持ejs语法。须要babel-loader把文件的内容转换成兼容性好的代码,而后用raw-loader把文件内容输出成字符串。注意这里的raw-loader安装的是0.5版本。html5

<script>
    ${require('raw-loader!babel-loader!../../../node_modules/lib-flexible/flexible.js')}
</script>

这样咱们打包出来的文件就是java

<script>
   flexible.js的内容
</script>

添加px2rem-loadernode

{
        test: /.scss$/,
        use: [
            MiniCssExtractPlugin.loader,
            'css-loader',
            {
                loader: 'px2rem-loader',
                options: {
                    remUnit: 75, // 1px=75rem
                    remPrecision: 8 // 计算rem保留的精度
                }
            },
            'sass-loader',
            {
                loader: 'postcss-loader',
                options: {
                    plugins: () => [
                        require('autoprefixer')({
                            overrideBrowserslist: ['last 2 version', '>1%', 'ios 7']
                        })
                    ]
                }
            }
        ]
}

提取公共资源

多页应用通用打包方案

这里主要是经过动态获取要打包的page路径,生成entry和对应的html-webpack-pluginreact

const setMAP = () => {
    const entry = {};
    const htmlWebpackPlugins = [];
    const entryFiles = glob.sync(path.join(__dirname, './src/pages/*/index.js'));

    Object.keys(entryFiles).forEach((index) => {
        const entryFile = entryFiles[index]
        const match = entryFile.match(/src\/pages\/(.*)\/index\.js/);
        const pageName = match && match[1];
        entry[pageName] = `./src/pages/${pageName}/index.js`
        console.log(pageName)
        htmlWebpackPlugins.push(new HtmlWebpackPlugin({
            template: path.join(__dirname, `./src/pages/${pageName}/${pageName}.html`),
            filename: `${pageName}.html`,
            chunks: [pageName],
            inject: true,
            minify: {
                html5: true,
                collapseWhitespace: true,
                preserveLineBreaks: false,
                minifyCSS: true,
                minifyJS: true,
                removeComments: false
            }
        }))
    })

    return {
        entry,
        htmlWebpackPlugins
    }
}

const { entry, htmlWebpackPlugins } = setMAP()

modules.export = {
    entry,
    plugins: [
    ].concat(htmlWebpackPlugins)
}

基础库分离

一种方案是经过html-webpack-externals-plugin,而后在html里面直接引入组件库的cdn连接webpack

const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin')
moudles.export = {
    plugins: [
        new HtmlWebpackExternalsPlugin({
            externals: [
                {
                    module: 'react',
                    entry: '//11.url.cn/now/lib/16.2.0/react.min.js',
                    global: 'React'
                },
                {
                    module: 'react-dom',
                    entry: '//11.url.cn/now/lib/16.2.0/react-dom.min.js',
                    global: 'ReactDom'
                }
            ]
        })
    ]
}

htmlios

<script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react.min.js"></script>
<script type="text/javascript" src="https://11.url.cn/now/lib/16.2.0/react-dom.min.js"></script>

另一种方法是经过webpack4的
SplitChunksPlugins实现,顺便提一下,webpack3使用的是commonChunksPluginweb

module.exports = {
    plugins: [
        new HtmlWebpackPlugin({
            template: path.join(__dirname, `./src/pages/search/search.html`),
            filename: `search.html`,
            chunks: ['vendors', 'common', 'search'], //注意这里要引入vendors跟common
            inject: true,
            minify: {
                html5: true,
                collapseWhitespace: true,
                preserveLineBreaks: false,
                minifyCSS: true,
                minifyJS: true,
                removeComments: false
            }
        })
    ]
    optimization: {
        splitChunks: {
            minSize: 0,
            cacheGroups: {
                vendors: {
                    test: /(react|react-dom)/,
                    name: 'vendors',
                    chunks: 'all',
                    priority: -10   // 须要设置权重才能都分离出来
                },
                common: {
                    name: 'commons',
                    chunks: 'all',
                    minChunks: 2,
                    priority: -20   
                }
            }
        }
    },
}

代码动态分割和import

ES6还不支持这个功能,须要借助babel插件实现。

npm install @babel/plugin-syntax-dynamic-import --save-dev

在babel的配置文件.babelrc里面添加

{
      "plugins": [
          "@babel/plugin-syntax-dynamic-import"
      ]
  }

使用的时候直接经过import函数引入某个组件

loadComponent () {
        import("./text.js").then((Text) => {
            console.log(Text)
            this.setState({
                Text: Text.default // 注意这里设置的是Text.default
            })
        })  
    }

这样就能够发现,text.js被打包成一个独立的js,当触发loadComponent在浏览器的network里面才看到这个文件。

优化显示日志

咱们在build的时候,可能只须要看到报错的日志,能够经过设置stats来控制要显示的日志。同时配合插件friendly-errors-webpack-plugin优化日志的输出。
stats参数:

modules.export {
    plugins: [
        new FriendlyErrorsWebpackPlugin()
    ],
    stats: 'errors-only'
}

打包组件跟库

react ssr简单demo

几个重要的概念

socucemap
tree shaking

概念:就是在构建的过程当中,删除掉咱们不须要用的代码。<br/>
优化原则:无用代码的判断,是根据DCE原则,某些代码不会被执行,或者是执行后的结果不会被用到,或者是执行的结果被用到的变量并无被使用,这些代码都是无效代码,在tree-shaking中要被优化掉的。<br/>
执行阶段:这里是经过静态分析,在编译阶段实现的<br/>
特色:使用ES6的import方法引入文件是能够进行tree-shaking,require是动态引入的文件,没法进行tree shaking, 由于不会在运行的时候还去分析优化代码。<br/>
如何开启:webpack4的production模式是默认会开启tree-shaking的

scope hoisting

webpack在编译的时候,会把import进来的模块用闭包函数包裹,而后经过__webpack_require__的形式使用。这样会致使两个问题。<br/>
一、打包的代码体积比较大。<br/>
二、运行时的内存开销比较大。<br/>

scope hoisting经过把import进来的模块,直接内联到同一个闭包函数中,经过替换变量名的方式,避免代码冲突,来减小代码里面的闭包函数。可是须要注意的是仅仅对只被引入过一次的函数使用这个方案,对屡次被引入的,咱们仍是但愿它是一个独立的闭包模块,便于屡次使用。特色:仅在ES6的import下生效,动态引入的require模式下不起做用。<br/>如何开启:webpack4的production模式是默认会开启tree-shaking的

相关文章
相关标签/搜索